Kstars

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

KDE's Doxygen guidelines are available online.