Kstars

cometscomponent.cpp
1/*
2 SPDX-FileCopyrightText: 2005 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "cometscomponent.h"
8
9#ifndef KSTARS_LITE
10#include "kstars.h"
11#endif
12#include "ksfilereader.h"
13#include "kspaths.h"
14#include "kstarsdata.h"
15#include "ksutils.h"
16#include "ksnotification.h"
17#include "kstars_debug.h"
18#ifndef KSTARS_LITE
19#include "skymap.h"
20#else
21#include "kstarslite.h"
22#endif
23#include "Options.h"
24#include "skylabeler.h"
25#include "skypainter.h"
26#include "solarsystemcomposite.h"
27#include "auxiliary/filedownloader.h"
28#include "auxiliary/kspaths.h"
29#include "projections/projector.h"
30#include "skyobjects/kscomet.h"
31
32#include <QFile>
33#include <QHttpMultiPart>
34#include <QPen>
35#include <QStandardPaths>
36
37#include <cmath>
38
44
46{
47 return Options::showComets();
48}
49
50/*
51 * @short Initialize the comets list.
52 * Reads in the comets data from the comets.dat file.
53 *
54 * Populate the list of Comets from the data file.
55 * The data file is a CSV file with the following columns :
56 * @li 1 full name [string]
57 * @li 2 modified julian day of orbital elements [int]
58 * @li 3 perihelion distance in AU [double]
59 * @li 4 eccentricity of orbit [double]
60 * @li 5 inclination angle of orbit in degrees [double]
61 * @li 6 argument of perihelion in degrees [double]
62 * @li 7 longitude of the ascending node in degrees [double]
63 * @li 8 time of perihelion passage (YYYYMMDD.DDD) [double]
64 * @li 9 orbit solution ID [string]
65 * @li 10 Near-Earth Object (NEO) flag [bool]
66 * @li 11 comet total magnitude parameter [float]
67 * @li 12 comet nuclear magnitude parameter [float]
68 * @li 13 object diameter (from equivalent sphere) [float]
69 * @li 14 object bi/tri-axial ellipsoid dimensions [string]
70 * @li 15 geometric albedo [float]
71 * @li 16 rotation period [float]
72 * @li 17 orbital period [float]
73 * @li 18 earth minimum orbit intersection distance [double]
74 * @li 19 orbit classification [string]
75 * @li 20 comet total magnitude slope parameter
76 * @li 21 comet nuclear magnitude slope parameter
77 * @note See KSComet constructor for more details.
78 */
79void CometsComponent::loadData()
80{
81 QString name, orbit_class;
82
83 emitProgressText(i18n("Loading comets"));
84 qCInfo(KSTARS) << "Loading comets";
85
86 qDeleteAll(m_ObjectList);
87 m_ObjectList.clear();
88
89 objectNames(SkyObject::COMET).clear();
90 objectLists(SkyObject::COMET).clear();
91
92 QString file_name = KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString("cometels.json.gz"));
93
94 try
95 {
96 KSUtils::MPCParser com_parser(file_name);
97 com_parser.for_each(
98 [&](const auto & get)
99 {
100 KSComet *com = nullptr;
101 name = get("Designation_and_name").toString();
102
103 int perihelion_year, perihelion_month, perihelion_day, perihelion_hour, perihelion_minute, perihelion_second;
104
105 // Perihelion Distance in AU
106 double perihelion_distance = get("Perihelion_dist").toDouble();
107 // Orbital Eccentricity
108 double eccentricity = get("e").toDouble();
109 // Argument of perihelion, J2000.0 (degrees)
110 double perihelion_argument = get("Peri").toDouble();
111 // Longitude of the ascending node, J2000.0 (degrees)
112 double ascending_node = get("Node").toDouble();
113 // Inclination in degrees, J2000.0 (degrees)
114 double inclination = get("i").toDouble();
115
116 // Perihelion Date
117 perihelion_year = get("Year_of_perihelion").toInt();
118 perihelion_month = get("Month_of_perihelion").toInt();
119 // Stored as double in MPC
120 double peri_day = get("Day_of_perihelion").toDouble();
121 perihelion_day = static_cast<int>(peri_day);
122 double peri_hour = (peri_day - perihelion_day) * 24;
123 perihelion_hour = static_cast<int>(peri_hour);
124 perihelion_minute = static_cast<int>((peri_hour - perihelion_hour) * 60);
125 perihelion_second = ( (( peri_hour - perihelion_hour) * 60) - perihelion_minute) * 60;
126
127 long double Tp = KStarsDateTime(QDate(perihelion_year, perihelion_month, perihelion_day),
128 QTime(perihelion_hour, perihelion_minute, perihelion_second)).djd();
129
130 // Orbit type
131 orbit_class = get("Orbit_type").toString();
132 double absolute_magnitude = get("H").toDouble();
133 double slope_parameter = get("G").toDouble();
134
135 com = new KSComet(name,
136 QString(),
137 perihelion_distance,
138 eccentricity,
139 dms(inclination),
140 dms(perihelion_argument),
141 dms(ascending_node),
142 Tp,
143 absolute_magnitude,
144 101.0,
145 slope_parameter,
146 101.0);
147
148 com->setOrbitClass(orbit_class);
149 com->setAngularSize(0.005);
150 appendListObject(com);
151
152 // Add *short* name to the list of object names
153 objectNames(SkyObject::COMET).append(com->name());
154 objectLists(SkyObject::COMET).append(QPair<QString, const SkyObject *>(com->name(), com));
155 });
156 }
157 catch (const std::runtime_error&)
158 {
159 qCInfo(KSTARS) << "Loading comets failed.";
160 qCInfo(KSTARS) << " -> was trying to read " + file_name;
161 return;
162 }
163}
164
165// Used for JPL Data
166// DO NOT REMOVE, we can revert to JPL at any time.
167//void CometsComponent::loadData()
168//{
169// QString name, orbit_id, orbit_class, dimensions;
170
171// emitProgressText(i18n("Loading comets"));
172// qCInfo(KSTARS) << "Loading comets";
173
174// qDeleteAll(m_ObjectList);
175// m_ObjectList.clear();
176
177// objectNames(SkyObject::COMET).clear();
178// objectLists(SkyObject::COMET).clear();
179
180// QString file_name =
181// KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString("comets.dat"));
182
183// try
184// {
185// KSUtils::JPLParser com_parser(file_name);
186// com_parser.for_each(
187// [&](const auto &get)
188// {
189// KSComet *com = nullptr;
190// name = get("full_name").toString();
191// name = name.trimmed();
192// bool neo;
193// double q, e, dble_i, dble_w, dble_N, Tp, earth_moid;
194// float M1, M2, K1, K2, diameter, albedo, rot_period, period;
195// q = get("q").toString().toDouble();
196// e = get("e").toString().toDouble();
197// dble_i = get("i").toString().toDouble();
198// dble_w = get("w").toString().toDouble();
199// dble_N = get("om").toString().toDouble();
200// Tp = get("tp").toString().toDouble();
201// orbit_id = get("orbit_id").toString();
202// neo = get("neo").toString() == "Y";
203
204// if (get("M1").toString().toFloat() == 0.0)
205// M1 = 101.0;
206// else
207// M1 = get("M1").toString().toFloat();
208
209// if (get("M2").toString().toFloat() == 0.0)
210// M2 = 101.0;
211// else
212// M2 = get("M2").toString().toFloat();
213
214// diameter = get("diameter").toString().toFloat();
215// dimensions = get("extent").toString();
216// albedo = get("albedo").toString().toFloat();
217// rot_period = get("rot_per").toString().toFloat();
218// period = get("per.y").toDouble();
219// earth_moid = get("moid").toString().toDouble();
220// orbit_class = get("class").toString();
221// K1 = get("H").toString().toFloat();
222// K2 = get("G").toString().toFloat();
223
224// com = new KSComet(name, QString(), q, e, dms(dble_i), dms(dble_w),
225// dms(dble_N), Tp, M1, M2, K1, K2);
226// com->setOrbitID(orbit_id);
227// com->setNEO(neo);
228// com->setDiameter(diameter);
229// com->setDimensions(dimensions);
230// com->setAlbedo(albedo);
231// com->setRotationPeriod(rot_period);
232// com->setPeriod(period);
233// com->setEarthMOID(earth_moid);
234// com->setOrbitClass(orbit_class);
235// com->setAngularSize(0.005);
236// appendListObject(com);
237
238// // Add *short* name to the list of object names
239// objectNames(SkyObject::COMET).append(com->name());
240// objectLists(SkyObject::COMET)
241// .append(QPair<QString, const SkyObject *>(com->name(), com));
242// });
243// }
244// catch (const std::runtime_error &e)
245// {
246// qCInfo(KSTARS) << "Loading comets failed.";
247// qCInfo(KSTARS) << " -> was trying to read " + file_name;
248// return;
249// }
250//}
251
253{
254 Q_UNUSED(skyp)
255#ifndef KSTARS_LITE
256 if (!selected() || Options::zoomFactor() < 1 * MINZOOM)
257 return;
258
259 bool hideLabels = !Options::showCometNames() || (SkyMap::Instance()->isSlewing() && Options::hideLabels());
260 double rsunLabelLimit = Options::maxRadCometName();
261
262 //FIXME: Should these be config'able?
263 skyp->setPen(QPen(QColor("transparent")));
264 skyp->setBrush(QBrush(QColor("white")));
265
266 for (auto so : m_ObjectList)
267 {
268 KSComet *com = dynamic_cast<KSComet *>(so);
269 double mag = com->mag();
270 if (std::isnan(mag) == 0)
271 {
272 bool drawn = skyp->drawComet(com);
273 if (drawn && !(hideLabels || com->rsun() >= rsunLabelLimit))
274 SkyLabeler::AddLabel(com, SkyLabeler::COMET_LABEL);
275 }
276 }
277#endif
278}
279
280// DO NOT REMOVE
281//void CometsComponent::updateDataFile(bool isAutoUpdate)
282//{
283// delete (downloadJob);
284// downloadJob = new FileDownloader();
285
286// if (isAutoUpdate == false)
287// downloadJob->setProgressDialogEnabled(true, i18n("Comets Update"),
288// i18n("Downloading comets updates..."));
289// downloadJob->registerDataVerification([&](const QByteArray &data)
290// { return data.startsWith("{\"signature\""); });
291
292// connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
293
294// // For auto-update, we ignore errors
295// if (isAutoUpdate == false)
296// connect(downloadJob, SIGNAL(error(QString)), this, SLOT(downloadError(QString)));
297
298// QUrl url = QUrl("https://ssd-api.jpl.nasa.gov/sbdb_query.api");
299// QByteArray post_data = KSUtils::getJPLQueryString(
300// "c",
301// "full_name,epoch.mjd,q,e,i,w,om,tp,orbit_id,neo,"
302// "M1,M2,diameter,extent,albedo,rot_per,per.y,moid,H,G,class",
303// QVector<KSUtils::JPLFilter>{});
304// // FIXME: find out what { "Af", "!=", "D" } used to mean
305
306// downloadJob->post(url, post_data);
307//}
308
309void CometsComponent::updateDataFile(bool isAutoUpdate)
310{
311 delete (downloadJob);
312 downloadJob = new FileDownloader();
313
314 if (isAutoUpdate == false)
315 downloadJob->setProgressDialogEnabled(true, i18n("Comets Update"),
316 i18n("Downloading comets updates..."));
317
318 connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
319
320 // For auto-update, we ignore errors
321 if (isAutoUpdate == false)
322 connect(downloadJob, SIGNAL(error(QString)), this, SLOT(downloadError(QString)));
323
324 QUrl url = QUrl("https://www.minorplanetcenter.net/Extended_Files/cometels.json.gz");
325 downloadJob->get(url);
326}
327
328void CometsComponent::downloadReady()
329{
330 // Comment the first line
331 QByteArray data = downloadJob->downloadedData();
332
333 // Write data to cometels.json.gz
334 QFile file(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
335 .filePath("cometels.json.gz"));
336 if (file.open(QIODevice::WriteOnly))
337 {
338 file.write(data);
339 file.close();
340 }
341 else
342 qCWarning(KSTARS) << "Failed writing comet data to" << file.fileName();
343
344 QString focusedComet;
345
346#ifdef KSTARS_LITE
348 if (foc && foc->type() == SkyObject::COMET)
349 {
350 focusedComet = foc->name();
352 }
353#else
355 if (foc && foc->type() == SkyObject::COMET)
356 {
357 focusedComet = foc->name();
358 KStars::Instance()->map()->setFocusObject(nullptr);
359 }
360#endif
361
362 // Reload comets
363 loadData();
364
365#ifdef KSTARS_LITE
367 if (!focusedComet.isEmpty())
369 KStarsLite::Instance()->data()->objectNamed(focusedComet));
370#else
371 if (!focusedComet.isEmpty())
373 KStars::Instance()->data()->objectNamed(focusedComet));
375#endif
376
377 downloadJob->deleteLater();
378}
379
380// DO NOT REMOVE
381//void CometsComponent::downloadReady()
382//{
383// // Comment the first line
384// QByteArray data = downloadJob->downloadedData();
385
386// // Write data to comets.dat
387// QFile file(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
388// .filePath("comets.dat"));
389// if (file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
390// {
391// file.write(data);
392// file.close();
393// }
394// else
395// qCWarning(KSTARS) << "Failed writing comet data to" << file.fileName();
396
397// QString focusedComet;
398
399//#ifdef KSTARS_LITE
400// SkyObject *foc = KStarsLite::Instance()->map()->focusObject();
401// if (foc && foc->type() == SkyObject::COMET)
402// {
403// focusedComet = foc->name();
404// KStarsLite::Instance()->map()->setFocusObject(nullptr);
405// }
406//#else
407// SkyObject *foc = KStars::Instance()->map()->focusObject();
408// if (foc && foc->type() == SkyObject::COMET)
409// {
410// focusedComet = foc->name();
411// KStars::Instance()->map()->setFocusObject(nullptr);
412// }
413//#endif
414
415// // Reload comets
416// loadData();
417
418//#ifdef KSTARS_LITE
419// KStarsLite::Instance()->data()->setFullTimeUpdate();
420// if (!focusedComet.isEmpty())
421// KStarsLite::Instance()->map()->setFocusObject(
422// KStarsLite::Instance()->data()->objectNamed(focusedComet));
423//#else
424// if (!focusedComet.isEmpty())
425// KStars::Instance()->map()->setFocusObject(
426// KStars::Instance()->data()->objectNamed(focusedComet));
427// KStars::Instance()->data()->setFullTimeUpdate();
428//#endif
429
430// downloadJob->deleteLater();
431//}
432
433void CometsComponent::downloadError(const QString &errorString)
434{
435 KSNotification::error(i18n("Error downloading asteroids data: %1", errorString));
436 qCCritical(KSTARS) << errorString;
437 downloadJob->deleteLater();
438}
CometsComponent(SolarSystemComposite *parent)
Default constructor.
bool selected() override
void draw(SkyPainter *skyp) override
Draw the object on the SkyMap skyp a pointer to the SkyPainter to use.
A subclass of KSPlanetBase that implements comets.
Definition kscomet.h:44
void setOrbitClass(QString orbit_class)
Sets the comet's orbit class.
Definition kscomet.cpp:326
void setAngularSize(double size)
set the planet's angular size, in km.
double rsun() const
void setFullTimeUpdate()
The Sky is updated more frequently than the moon, which is updated more frequently than the planets.
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
long double djd() const
SkyMapLite * map() const
Definition kstarslite.h:80
static KStarsLite * Instance()
Definition kstarslite.h:77
KStarsData * data() const
Definition kstarslite.h:86
SkyMap * map() const
Definition kstars.h:141
static KStars * Instance()
Definition kstars.h:123
KStarsData * data() const
Definition kstars.h:135
void appendListObject(SkyObject *object)
Add an object to the Object list.
virtual void emitProgressText(const QString &message)
Emit signal about progress.
static void AddLabel(SkyObject *obj, label_t type)
static version of addLabel() below.
Definition skylabeler.h:135
void setFocusObject(SkyObject *o)
Set the FocusObject pointer to the argument.
SkyObject * focusObject() const
Retrieve the object which is centered in the sky map.
Definition skymaplite.h:252
void setFocusObject(SkyObject *o)
Set the FocusObject pointer to the argument.
Definition skymap.cpp:371
SkyObject * focusObject() const
Retrieve the object which is centered in the sky map.
Definition skymap.h:262
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
virtual QString name(void) const
Definition skyobject.h:145
int type(void) const
Definition skyobject.h:188
float mag() const
Definition skyobject.h:206
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
virtual bool drawComet(KSComet *com)=0
Draw a comet in the sky.
virtual void setBrush(const QBrush &brush)=0
Set the brush of the painter.
virtual void setPen(const QPen &pen)=0
Set the pen of the painter.
The solar system composite manages all planets, asteroids and comets.
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
QString i18n(const char *text, const TYPE &arg...)
void clear()
void clear()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:59:52 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.