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 clear();
87 objectNames(SkyObject::COMET).clear();
88 objectLists(SkyObject::COMET).clear();
89
90 QString file_name = KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString("cometels.json.gz"));
91
92 try
93 {
94 KSUtils::MPCParser com_parser(file_name);
95 com_parser.for_each(
96 [&](const auto & get)
97 {
98 KSComet *com = nullptr;
99 name = get("Designation_and_name").toString();
100
101 int perihelion_year, perihelion_month, perihelion_day, perihelion_hour, perihelion_minute, perihelion_second;
102
103 // Perihelion Distance in AU
104 double perihelion_distance = get("Perihelion_dist").toDouble();
105 // Orbital Eccentricity
106 double eccentricity = get("e").toDouble();
107 // Argument of perihelion, J2000.0 (degrees)
108 double perihelion_argument = get("Peri").toDouble();
109 // Longitude of the ascending node, J2000.0 (degrees)
110 double ascending_node = get("Node").toDouble();
111 // Inclination in degrees, J2000.0 (degrees)
112 double inclination = get("i").toDouble();
113
114 // Perihelion Date
115 perihelion_year = get("Year_of_perihelion").toInt();
116 perihelion_month = get("Month_of_perihelion").toInt();
117 // Stored as double in MPC
118 double peri_day = get("Day_of_perihelion").toDouble();
119 perihelion_day = static_cast<int>(peri_day);
120 double peri_hour = (peri_day - perihelion_day) * 24;
121 perihelion_hour = static_cast<int>(peri_hour);
122 perihelion_minute = static_cast<int>((peri_hour - perihelion_hour) * 60);
123 perihelion_second = ( (( peri_hour - perihelion_hour) * 60) - perihelion_minute) * 60;
124
125 long double Tp = KStarsDateTime(QDate(perihelion_year, perihelion_month, perihelion_day),
126 QTime(perihelion_hour, perihelion_minute, perihelion_second)).djd();
127
128 // Orbit type
129 orbit_class = get("Orbit_type").toString();
130 double absolute_magnitude = get("H").toDouble();
131 double slope_parameter = get("G").toDouble();
132
133 com = new KSComet(name,
134 QString(),
135 perihelion_distance,
136 eccentricity,
137 dms(inclination),
138 dms(perihelion_argument),
139 dms(ascending_node),
140 Tp,
141 absolute_magnitude,
142 101.0,
143 slope_parameter,
144 101.0);
145
146 com->setOrbitClass(orbit_class);
147 com->setAngularSize(0.005);
148 appendListObject(com);
149
150 // Add *short* name to the list of object names
151 objectNames(SkyObject::COMET).append(com->name());
152 objectLists(SkyObject::COMET).append(QPair<QString, const SkyObject *>(com->name(), com));
153 });
154 }
155 catch (const std::runtime_error &)
156 {
157 qCInfo(KSTARS) << "Loading comets failed.";
158 qCInfo(KSTARS) << " -> was trying to read " + file_name;
159 return;
160 }
161}
162
163// Used for JPL Data
164// DO NOT REMOVE, we can revert to JPL at any time.
165//void CometsComponent::loadData()
166//{
167// QString name, orbit_id, orbit_class, dimensions;
168
169// emitProgressText(i18n("Loading comets"));
170// qCInfo(KSTARS) << "Loading comets";
171
172// qDeleteAll(m_ObjectList);
173// m_ObjectList.clear();
174
175// objectNames(SkyObject::COMET).clear();
176// objectLists(SkyObject::COMET).clear();
177
178// QString file_name =
179// KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString("comets.dat"));
180
181// try
182// {
183// KSUtils::JPLParser com_parser(file_name);
184// com_parser.for_each(
185// [&](const auto &get)
186// {
187// KSComet *com = nullptr;
188// name = get("full_name").toString();
189// name = name.trimmed();
190// bool neo;
191// double q, e, dble_i, dble_w, dble_N, Tp, earth_moid;
192// float M1, M2, K1, K2, diameter, albedo, rot_period, period;
193// q = get("q").toString().toDouble();
194// e = get("e").toString().toDouble();
195// dble_i = get("i").toString().toDouble();
196// dble_w = get("w").toString().toDouble();
197// dble_N = get("om").toString().toDouble();
198// Tp = get("tp").toString().toDouble();
199// orbit_id = get("orbit_id").toString();
200// neo = get("neo").toString() == "Y";
201
202// if (get("M1").toString().toFloat() == 0.0)
203// M1 = 101.0;
204// else
205// M1 = get("M1").toString().toFloat();
206
207// if (get("M2").toString().toFloat() == 0.0)
208// M2 = 101.0;
209// else
210// M2 = get("M2").toString().toFloat();
211
212// diameter = get("diameter").toString().toFloat();
213// dimensions = get("extent").toString();
214// albedo = get("albedo").toString().toFloat();
215// rot_period = get("rot_per").toString().toFloat();
216// period = get("per.y").toDouble();
217// earth_moid = get("moid").toString().toDouble();
218// orbit_class = get("class").toString();
219// K1 = get("H").toString().toFloat();
220// K2 = get("G").toString().toFloat();
221
222// com = new KSComet(name, QString(), q, e, dms(dble_i), dms(dble_w),
223// dms(dble_N), Tp, M1, M2, K1, K2);
224// com->setOrbitID(orbit_id);
225// com->setNEO(neo);
226// com->setDiameter(diameter);
227// com->setDimensions(dimensions);
228// com->setAlbedo(albedo);
229// com->setRotationPeriod(rot_period);
230// com->setPeriod(period);
231// com->setEarthMOID(earth_moid);
232// com->setOrbitClass(orbit_class);
233// com->setAngularSize(0.005);
234// appendListObject(com);
235
236// // Add *short* name to the list of object names
237// objectNames(SkyObject::COMET).append(com->name());
238// objectLists(SkyObject::COMET)
239// .append(QPair<QString, const SkyObject *>(com->name(), com));
240// });
241// }
242// catch (const std::runtime_error &e)
243// {
244// qCInfo(KSTARS) << "Loading comets failed.";
245// qCInfo(KSTARS) << " -> was trying to read " + file_name;
246// return;
247// }
248//}
249
251{
252 Q_UNUSED(skyp)
253#ifndef KSTARS_LITE
254 if (!selected() || Options::zoomFactor() < 1 * MINZOOM)
255 return;
256
257 bool hideLabels = !Options::showCometNames() || (SkyMap::Instance()->isSlewing() && Options::hideLabels());
258 double rsunLabelLimit = Options::maxRadCometName();
259
260 //FIXME: Should these be config'able?
261 skyp->setPen(QPen(QColor("transparent")));
262 skyp->setBrush(QBrush(QColor("white")));
263
264 for (auto so : m_ObjectList)
265 {
266 KSComet *com = dynamic_cast<KSComet *>(so);
267 double mag = com->mag();
268 if (std::isnan(mag) == 0)
269 {
270 bool drawn = skyp->drawComet(com);
271 if (drawn && !(hideLabels || com->rsun() >= rsunLabelLimit))
272 SkyLabeler::AddLabel(com, SkyLabeler::COMET_LABEL);
273 }
274 }
275#endif
276}
277
278// DO NOT REMOVE
279//void CometsComponent::updateDataFile(bool isAutoUpdate)
280//{
281// delete (downloadJob);
282// downloadJob = new FileDownloader();
283
284// if (isAutoUpdate == false)
285// downloadJob->setProgressDialogEnabled(true, i18n("Comets Update"),
286// i18n("Downloading comets updates..."));
287// downloadJob->registerDataVerification([&](const QByteArray &data)
288// { return data.startsWith("{\"signature\""); });
289
290// connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
291
292// // For auto-update, we ignore errors
293// if (isAutoUpdate == false)
294// connect(downloadJob, SIGNAL(error(QString)), this, SLOT(downloadError(QString)));
295
296// QUrl url = QUrl("https://ssd-api.jpl.nasa.gov/sbdb_query.api");
297// QByteArray post_data = KSUtils::getJPLQueryString(
298// "c",
299// "full_name,epoch.mjd,q,e,i,w,om,tp,orbit_id,neo,"
300// "M1,M2,diameter,extent,albedo,rot_per,per.y,moid,H,G,class",
301// QVector<KSUtils::JPLFilter>{});
302// // FIXME: find out what { "Af", "!=", "D" } used to mean
303
304// downloadJob->post(url, post_data);
305//}
306
307void CometsComponent::updateDataFile(bool isAutoUpdate)
308{
309 delete (downloadJob);
310 downloadJob = new FileDownloader();
311
312 if (isAutoUpdate == false)
313 downloadJob->setProgressDialogEnabled(true, i18n("Comets Update"),
314 i18n("Downloading comets updates..."));
315
316 connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
317
318 // For auto-update, we ignore errors
319 if (isAutoUpdate == false)
320 connect(downloadJob, SIGNAL(error(QString)), this, SLOT(downloadError(QString)));
321
322 QUrl url = QUrl("https://www.minorplanetcenter.net/Extended_Files/cometels.json.gz");
323 downloadJob->get(url);
324}
325
326void CometsComponent::downloadReady()
327{
328 // Comment the first line
329 QByteArray data = downloadJob->downloadedData();
330
331 // Write data to cometels.json.gz
332 QFile file(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
333 .filePath("cometels.json.gz"));
334 if (file.open(QIODevice::WriteOnly))
335 {
336 file.write(data);
337 file.close();
338 }
339 else
340 qCWarning(KSTARS) << "Failed writing comet data to" << file.fileName();
341
342 QString focusedComet;
343
344#ifdef KSTARS_LITE
346 if (foc && foc->type() == SkyObject::COMET)
347 {
348 focusedComet = foc->name();
350 }
351#else
353 if (foc && foc->type() == SkyObject::COMET)
354 {
355 focusedComet = foc->name();
356 KStars::Instance()->map()->setFocusObject(nullptr);
357 }
358#endif
359
360 // Reload comets
361 loadData();
362
363#ifdef KSTARS_LITE
365 if (!focusedComet.isEmpty())
367 KStarsLite::Instance()->data()->objectNamed(focusedComet));
368#else
369 if (!focusedComet.isEmpty())
371 KStars::Instance()->data()->objectNamed(focusedComet));
373#endif
374
375 downloadJob->deleteLater();
376}
377
378// DO NOT REMOVE
379//void CometsComponent::downloadReady()
380//{
381// // Comment the first line
382// QByteArray data = downloadJob->downloadedData();
383
384// // Write data to comets.dat
385// QFile file(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
386// .filePath("comets.dat"));
387// if (file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
388// {
389// file.write(data);
390// file.close();
391// }
392// else
393// qCWarning(KSTARS) << "Failed writing comet data to" << file.fileName();
394
395// QString focusedComet;
396
397//#ifdef KSTARS_LITE
398// SkyObject *foc = KStarsLite::Instance()->map()->focusObject();
399// if (foc && foc->type() == SkyObject::COMET)
400// {
401// focusedComet = foc->name();
402// KStarsLite::Instance()->map()->setFocusObject(nullptr);
403// }
404//#else
405// SkyObject *foc = KStars::Instance()->map()->focusObject();
406// if (foc && foc->type() == SkyObject::COMET)
407// {
408// focusedComet = foc->name();
409// KStars::Instance()->map()->setFocusObject(nullptr);
410// }
411//#endif
412
413// // Reload comets
414// loadData();
415
416//#ifdef KSTARS_LITE
417// KStarsLite::Instance()->data()->setFullTimeUpdate();
418// if (!focusedComet.isEmpty())
419// KStarsLite::Instance()->map()->setFocusObject(
420// KStarsLite::Instance()->data()->objectNamed(focusedComet));
421//#else
422// if (!focusedComet.isEmpty())
423// KStars::Instance()->map()->setFocusObject(
424// KStars::Instance()->data()->objectNamed(focusedComet));
425// KStars::Instance()->data()->setFullTimeUpdate();
426//#endif
427
428// downloadJob->deleteLater();
429//}
430
431void CometsComponent::downloadError(const QString &errorString)
432{
433 KSNotification::error(i18n("Error downloading asteroids data: %1", errorString));
434 qCCritical(KSTARS) << errorString;
435 downloadJob->deleteLater();
436}
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:328
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()
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 Oct 11 2024 12:15:12 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.