Marble

SunLocator.cpp
1 // SPDX-FileCopyrightText: 2007-2009 David Roberts <[email protected]>
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 
18 namespace Marble
19 {
20 
21 using std::sin;
22 
23 class SunLocatorPrivate
24 {
25 public:
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 
46 SunLocator::SunLocator( const MarbleClock *clock, const Planet *planet )
47  : QObject(),
48  d( new SunLocatorPrivate( clock, planet ))
49 {
50 }
51 
52 SunLocator::~SunLocator()
53 {
54  delete d;
55 }
56 
57 qreal 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 
83 void 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 
105 void 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 
133 void 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 
140 void 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 
165 qreal SunLocator::getLon() const
166 {
167  return d->m_lon * RAD2DEG;
168 }
169 
170 qreal 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.
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Oct 2 2023 03:52:10 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.