Kstars

modcalcdaylength.cpp
1/*
2 SPDX-FileCopyrightText: 2002 Pablo de Vicente <vicente@oan.es>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "modcalcdaylength.h"
8
9#include "geolocation.h"
10#include "kstarsdata.h"
11#include "ksnotification.h"
12#include "dialogs/locationdialog.h"
13#include "skyobjects/ksmoon.h"
14#include "skyobjects/kssun.h"
15#include "skyobjects/skyobject.h"
16
17#include <KLineEdit>
18#include <KLocalizedString>
19
20// Qt version calming
21#include <qtendl.h>
22
23modCalcDayLength::modCalcDayLength(QWidget *parentSplit) : QFrame(parentSplit)
24{
25 setupUi(this);
26
27 showCurrentDate();
28 initGeo();
29 slotComputeAlmanac();
30
31 connect(Date, SIGNAL(dateChanged(QDate)), this, SLOT(slotComputeAlmanac()));
32 connect(Location, SIGNAL(clicked()), this, SLOT(slotLocation()));
33
34 connect(LocationBatch, SIGNAL(clicked()), this, SLOT(slotLocationBatch()));
35 connect(InputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
36 connect(OutputFileBatch, SIGNAL(urlSelected(QUrl)), this, SLOT(slotCheckFiles()));
37 connect(RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch()));
38 connect(ViewButtonBatch, SIGNAL(clicked()), this, SLOT(slotViewBatch()));
39
40 RunButtonBatch->setEnabled(false);
41 ViewButtonBatch->setEnabled(false);
42
43 show();
44}
45
46void modCalcDayLength::showCurrentDate(void)
47{
49 Date->setDate(dt.date());
50}
51
52void modCalcDayLength::initGeo(void)
53{
54 KStarsData *data = KStarsData::Instance();
55 geoPlace = data->geo();
56 geoBatch = data->geo();
57 Location->setText(geoPlace->fullName());
58 LocationBatch->setText(geoBatch->fullName());
59}
60
61QTime modCalcDayLength::lengthOfDay(const QTime &setQTime, const QTime &riseQTime)
62{
63 QTime dL(0, 0, 0);
64 int dds = riseQTime.secsTo(setQTime);
65 QTime dLength = dL.addSecs(dds);
66
67 return dLength;
68}
69
70void modCalcDayLength::slotLocation()
71{
73 if (ld->exec() == QDialog::Accepted)
74 {
75 GeoLocation *newGeo = ld->selectedCity();
76 if (newGeo)
77 {
78 geoPlace = newGeo;
79 Location->setText(geoPlace->fullName());
80 }
81 }
82 delete ld;
83
84 slotComputeAlmanac();
85}
86
87void modCalcDayLength::slotLocationBatch()
88{
90 if (ld->exec() == QDialog::Accepted)
91 {
92 GeoLocation *newGeo = ld->selectedCity();
93 if (newGeo)
94 {
95 geoBatch = newGeo;
96 LocationBatch->setText(geoBatch->fullName());
97 }
98 }
99 delete ld;
100}
101
102void modCalcDayLength::updateAlmanac(const QDate &d, GeoLocation *geo)
103{
104 //Determine values needed for the Almanac
105 long double jd0 = KStarsDateTime(d, QTime(8, 0, 0)).djd();
106 KSNumbers num(jd0);
107
108 //Sun
109 KSSun Sun;
110 Sun.findPosition(&num);
111
112 QTime ssTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, false);
113 QTime srTime = Sun.riseSetTime(KStarsDateTime(jd0), geo, true);
114 QTime stTime = Sun.transitTime(KStarsDateTime(jd0), geo);
115
116 dms ssAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, false);
117 dms srAz = Sun.riseSetTimeAz(KStarsDateTime(jd0), geo, true);
118 dms stAlt = Sun.transitAltitude(KStarsDateTime(jd0), geo);
119
120 //In most cases, the Sun will rise and set:
121 if (ssTime.isValid())
122 {
123 ssAzString = ssAz.toDMSString();
124 stAltString = stAlt.toDMSString();
125 srAzString = srAz.toDMSString();
126
127 ssTimeString = QLocale().toString(ssTime, "hh:mm:ss");
128 srTimeString = QLocale().toString(srTime, "hh:mm:ss");
129 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
130
131 QTime daylength = lengthOfDay(ssTime, srTime);
132 //daylengthString = QLocale().toString(daylength);
133 daylengthString = QLocale().toString(daylength, "hh:mm:ss");
134
135 //...but not always!
136 }
137 else if (stAlt.Degrees() > 0.)
138 {
139 ssAzString = i18n("Circumpolar");
140 stAltString = stAlt.toDMSString();
141 srAzString = i18n("Circumpolar");
142
143 ssTimeString = "--:--";
144 srTimeString = "--:--";
145 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
146 daylengthString = "24:00";
147 }
148 else if (stAlt.Degrees() < 0.)
149 {
150 ssAzString = i18n("Does not rise");
151 stAltString = stAlt.toDMSString();
152 srAzString = i18n("Does not set");
153
154 ssTimeString = "--:--";
155 srTimeString = "--:--";
156 stTimeString = QLocale().toString(stTime, "hh:mm:ss");
157 daylengthString = "00:00";
158 }
159
160 //Moon
161 KSMoon Moon;
162
163 QTime msTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, false);
164 QTime mrTime = Moon.riseSetTime(KStarsDateTime(jd0), geo, true);
165 QTime mtTime = Moon.transitTime(KStarsDateTime(jd0), geo);
166
167 dms msAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, false);
168 dms mrAz = Moon.riseSetTimeAz(KStarsDateTime(jd0), geo, true);
169 dms mtAlt = Moon.transitAltitude(KStarsDateTime(jd0), geo);
170
171 //In most cases, the Moon will rise and set:
172 if (msTime.isValid())
173 {
174 msAzString = msAz.toDMSString();
175 mtAltString = mtAlt.toDMSString();
176 mrAzString = mrAz.toDMSString();
177
178 msTimeString = QLocale().toString(msTime, "hh:mm:ss");
179 mrTimeString = QLocale().toString(mrTime, "hh:mm:ss");
180 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
181
182 //...but not always!
183 }
184 else if (mtAlt.Degrees() > 0.)
185 {
186 msAzString = i18n("Circumpolar");
187 mtAltString = mtAlt.toDMSString();
188 mrAzString = i18n("Circumpolar");
189
190 msTimeString = "--:--";
191 mrTimeString = "--:--";
192 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
193 }
194 else if (mtAlt.Degrees() < 0.)
195 {
196 msAzString = i18n("Does not rise");
197 mtAltString = mtAlt.toDMSString();
198 mrAzString = i18n("Does not rise");
199
200 msTimeString = "--:--";
201 mrTimeString = "--:--";
202 mtTimeString = QLocale().toString(mtTime, "hh:mm:ss");
203 }
204
205 //after calling riseSetTime Phase needs to reset, setting it before causes Phase to set nan
206 Moon.findPosition(&num);
207 Moon.findPhase(nullptr);
208 lunarphaseString = i18nc("%2 is the value, % is the percent sign", "%1 (%2%)", Moon.phaseName(), QString::number(int(100 * Moon.illum())));
209
210 //Fix length of Az strings
211 if (srAz.Degrees() < 100.0)
212 srAzString = ' ' + srAzString;
213 if (ssAz.Degrees() < 100.0)
214 ssAzString = ' ' + ssAzString;
215 if (mrAz.Degrees() < 100.0)
216 mrAzString = ' ' + mrAzString;
217 if (msAz.Degrees() < 100.0)
218 msAzString = ' ' + msAzString;
219}
220
221void modCalcDayLength::slotComputeAlmanac()
222{
223 updateAlmanac(Date->date(), geoPlace);
224
225 SunSet->setText(ssTimeString);
226 SunRise->setText(srTimeString);
227 SunTransit->setText(stTimeString);
228 SunSetAz->setText(ssAzString);
229 SunRiseAz->setText(srAzString);
230 SunTransitAlt->setText(stAltString);
231 DayLength->setText(daylengthString);
232
233 MoonSet->setText(msTimeString);
234 MoonRise->setText(mrTimeString);
235 MoonTransit->setText(mtTimeString);
236 MoonSetAz->setText(msAzString);
237 MoonRiseAz->setText(mrAzString);
238 MoonTransitAlt->setText(mtAltString);
239 LunarPhase->setText(lunarphaseString);
240}
241
242void modCalcDayLength::slotCheckFiles()
243{
244 bool flag = !InputFileBatch->lineEdit()->text().isEmpty() && !OutputFileBatch->lineEdit()->text().isEmpty();
245 RunButtonBatch->setEnabled(flag);
246}
247
248void modCalcDayLength::slotRunBatch()
249{
250 QString inputFileName = InputFileBatch->url().toLocalFile();
251
252 if (QFile::exists(inputFileName))
253 {
254 QFile f(inputFileName);
255 if (!f.open(QIODevice::ReadOnly))
256 {
257 QString message = i18n("Could not open file %1.", f.fileName());
258 KSNotification::sorry(message, i18n("Could Not Open File"));
259 return;
260 }
261
262 QTextStream istream(&f);
263 processLines(istream);
264 ViewButtonBatch->setEnabled(true);
265
266 f.close();
267 }
268 else
269 {
270 QString message = i18n("Invalid file: %1", inputFileName);
271 KSNotification::sorry(message, i18n("Invalid file"));
272 return;
273 }
274}
275
276void modCalcDayLength::processLines(QTextStream &istream)
277{
278 QFile fOut(OutputFileBatch->url().toLocalFile());
279 fOut.open(QIODevice::WriteOnly);
280 QTextStream ostream(&fOut);
281
282 //Write header
283 ostream << "# " << i18nc("%1 is a location on earth", "Almanac for %1", geoBatch->fullName())
284 << QString(" [%1, %2]").arg(geoBatch->lng()->toDMSString(), geoBatch->lat()->toDMSString())
285 << "\n# " << i18n("computed by KStars") << Qt::endl
286 << "# " << "SRise: Sun Rise" << Qt::endl
287 << "# " << "STran: Sun Transit" << Qt::endl
288 << "# " << "SSet: Sun Set" << Qt::endl
289 << "# " << "SRiseAz: Azimuth of Sun Rise" << Qt::endl
290 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl
291 << "# " << "SSetAz: Azimuth of Sun Set" << Qt::endl
292 << "# " << "STranAlt: Altitude of Sun Transit" << Qt::endl
293 << "# " << "DayLen: Day Duration in hours" << Qt::endl
294 << "# " << "MRise: Moon Rise" << Qt::endl
295 << "# " << "MTran: Moon Transit" << Qt::endl
296 << "# " << "MSet: Moon Set" << Qt::endl
297 << "# " << "MRiseAz: Azimuth of Moon Rise" << Qt::endl
298 << "# " << "MTranAkt: Altitude of Moon Transit" << Qt::endl
299 << "# " << "MSetAz: Azimuth of Moon Set" << Qt::endl
300 << "# " << "LunarPhase: Lunar Phase and Illumination Percentage" << Qt::endl
301 << "# " << Qt::endl
302 << "# Date,SRise,STran,SSet,SRiseAz,STranAlt,SSetAz,DayLen,MRise,MTran,MSet,"
303 << "MRiseAz,MTranAlt,MSetAz,LunarPhase" << Qt::endl
304 << "#" << Qt::endl;
305
306 QString line;
307 QDate d;
308
309 while (!istream.atEnd())
310 {
311 line = istream.readLine();
312 line = line.trimmed();
313
314 //Parse the line as a date, then compute Almanac values
316 if (d.isValid())
317 {
318 updateAlmanac(d, geoBatch);
319 ostream << d.toString(Qt::ISODate) << "," <<
320 srTimeString << "," <<
321 stTimeString << "," <<
322 ssTimeString << "," <<
323 srAzString << "," <<
324 stAltString << "," <<
325 ssAzString << "," <<
326 daylengthString << "," <<
327 mrTimeString << "," <<
328 mtTimeString << "," <<
329 msTimeString << "," <<
330 mrAzString << "," <<
331 mtAltString << "," <<
332 msAzString << "," <<
333 lunarphaseString << Qt::endl;
334 }
335 }
336}
337
338void modCalcDayLength::slotViewBatch()
339{
340 QFile fOut(OutputFileBatch->url().toLocalFile());
341 fOut.open(QIODevice::ReadOnly);
342 QTextStream istream(&fOut);
343 QStringList text;
344
345 while (!istream.atEnd())
346 text.append(istream.readLine());
347
348 fOut.close();
349
350 KMessageBox::informationList(nullptr, i18n("Results of Almanac calculation"), text, OutputFileBatch->url().toLocalFile());
351}
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
QString fullName() const
const CachingDms * lat() const
Definition geolocation.h:70
const CachingDms * lng() const
Definition geolocation.h:64
Provides necessary information about the Moon.
Definition ksmoon.h:26
QString phaseName() const
Definition ksmoon.cpp:288
double illum() const
Definition ksmoon.h:49
void findPhase(const KSSun *Sun=nullptr)
Determine the phase angle of the moon, and assign the appropriate moon image.
Definition ksmoon.cpp:268
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
void findPosition(const KSNumbers *num, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, const KSPlanetBase *Earth=nullptr)
Find position, including correction for Figure-of-the-Earth.
Child class of KSPlanetBase; encapsulates information about the Sun.
Definition kssun.h:24
KStarsData is the backbone of KStars.
Definition kstarsdata.h:72
GeoLocation * geo()
Definition kstarsdata.h:230
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
static KStarsDateTime currentDateTime()
long double djd() const
Dialog for changing the geographic location of the observer.
dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const
dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo) const
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
Definition skyobject.cpp:93
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:287
const double & Degrees() const
Definition dms.h:141
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void informationList(QWidget *parent, const QString &text, const QStringList &strlist, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
QDate fromString(QStringView string, QStringView format, QCalendar cal)
bool exists() const const
void append(QList< T > &&value)
QString toString(QDate date, FormatType format) const const
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QString trimmed() const const
QTextStream & endl(QTextStream &stream)
bool atEnd() const const
QString readLine(qint64 maxlen)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime addSecs(int s) const const
bool isValid(int h, int m, int s, int ms)
int secsTo(QTime t) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.