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
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);
126
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(),
142 Tp,
144 101.0,
146 101.0);
147
148 com->setOrbitClass(orbit_class);
149 com->setAngularSize(0.005);
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{
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
345
346#ifdef KSTARS_LITE
347 SkyObject *foc = KStarsLite::Instance()->map()->focusObject();
348 if (foc && foc->type() == SkyObject::COMET)
349 {
350 focusedComet = foc->name();
351 KStarsLite::Instance()->map()->setFocusObject(nullptr);
352 }
353#else
354 SkyObject *foc = KStars::Instance()->map()->focusObject();
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
366 KStarsLite::Instance()->data()->setFullTimeUpdate();
367 if (!focusedComet.isEmpty())
368 KStarsLite::Instance()->map()->setFocusObject(
369 KStarsLite::Instance()->data()->objectNamed(focusedComet));
370#else
371 if (!focusedComet.isEmpty())
372 KStars::Instance()->map()->setFocusObject(
373 KStars::Instance()->data()->objectNamed(focusedComet));
374 KStars::Instance()->data()->setFullTimeUpdate();
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
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
long double djd() const
static KStarsLite * Instance()
Definition kstarslite.h:77
static KStars * Instance()
Definition kstars.h:123
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
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
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...)
Int toInt() const const
void clear()
void clear()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.