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 "MarbleGlobal.h"
8#include "MarbleClock.h"
9#include "Planet.h"
10#include "MarbleMath.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
45
46SunLocator::SunLocator( const MarbleClock *clock, const Planet *planet )
47 : QObject(),
48 d( new SunLocatorPrivate( clock, planet ))
49{
50}
51
52SunLocator::~SunLocator()
53{
54 delete d;
55}
56
57qreal SunLocator::shading(qreal lon, qreal a, qreal c) const
58{
59 // haversine formula
60 qreal b = sin((lon-d->m_lon)/2.0);
61// qreal g = sin((lat-d->m_lat)/2.0);
62// qreal h = (g*g)+cos(lat)*cos(d->m_lat)*(b*b);
63 qreal h = (a*a) + c * (b*b);
64
65 /*
66 h = 0.0 // directly beneath sun
67 h = 0.5 // sunrise/sunset line
68 h = 1.0 // opposite side of earth to the sun
69 theta = 2*asin(sqrt(h))
70 */
71
72 qreal brightness;
73 if ( h <= 0.5 - d->m_twilightZone / 2.0 )
74 brightness = 1.0;
75 else if ( h >= 0.5 + d->m_twilightZone / 2.0 )
76 brightness = 0.0;
77 else
78 brightness = ( 0.5 + d->m_twilightZone/2.0 - h ) / d->m_twilightZone;
79
80 return brightness;
81}
82
83void SunLocator::shadePixel(QRgb &pixcol, qreal brightness)
84{
85 // daylight - no change
86 if ( brightness > 0.99999 )
87 return;
88
89 if ( brightness < 0.00001 ) {
90 // night
91 // Doing "pixcol = qRgb(r/2, g/2, b/2);" by shifting some electrons around ;)
92 // by shifting some electrons around ;)
93 pixcol = qRgb(qRed(pixcol) * 0.35, qGreen(pixcol) * 0.35, qBlue(pixcol) * 0.35);
94 // pixcol = (pixcol & 0xff000000) | ((pixcol >> 1) & 0x7f7f7f);
95 } else {
96 // gradual shadowing
97 int r = qRed( pixcol );
98 int g = qGreen( pixcol );
99 int b = qBlue( pixcol );
100 qreal d = 0.65 * brightness + 0.35;
101 pixcol = qRgb((int)(d * r), (int)(d * g), (int)(d * b));
102 }
103}
104
105void SunLocator::shadePixelComposite(QRgb &pixcol, const QRgb &dpixcol,
106 qreal brightness)
107{
108 // daylight - no change
109 if ( brightness > 0.99999 )
110 return;
111
112 if ( brightness < 0.00001 ) {
113 // night
114 pixcol = dpixcol;
115 } else {
116 // gradual shadowing
117 qreal& d = brightness;
118
119 int r = qRed( pixcol );
120 int g = qGreen( pixcol );
121 int b = qBlue( pixcol );
122
123 int dr = qRed( dpixcol );
124 int dg = qGreen( dpixcol );
125 int db = qBlue( dpixcol );
126
127 pixcol = qRgb( (int)( d * r + (1 - d) * dr ),
128 (int)( d * g + (1 - d) * dg ),
129 (int)( d * b + (1 - d) * db ) );
130 }
131}
132
133void SunLocator::update()
134{
135 d->m_planet->sunPosition(d->m_lon, d->m_lat, d->m_clock->dateTime());
136
137 emit positionChanged( getLon(), getLat() );
138}
139
140void SunLocator::setPlanet( const Planet *planet )
141{
142 /*
143 // This won't work as expected if the same pointer
144 // points to different planets
145 if ( planet == d->m_planet ) {
146 return;
147 }
148 */
149
150 const Planet *previousPlanet = d->m_planet;
151
152 mDebug() << "SunLocator::setPlanet(Planet*)";
153 d->m_planet = planet;
154 d->m_twilightZone = planet->twilightZone();
155 planet->sunPosition(d->m_lon, d->m_lat, d->m_clock->dateTime());
156
157 // Initially there might be no planet set.
158 // In that case we don't want an update.
159 // Update the shading in all other cases.
160 if ( !previousPlanet->id().isEmpty() ) {
161 emit positionChanged( getLon(), getLat() );
162 }
163}
164
165qreal SunLocator::getLon() const
166{
167 return d->m_lon * RAD2DEG;
168}
169
170qreal SunLocator::getLat() const
171{
172 return d->m_lat * RAD2DEG;
173}
174
175}
176
177#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 Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.