Kstars

starcomponent.cpp
1/*
2 SPDX-FileCopyrightText: 2005 Thomas Kabelmann <thomas.kabelmann@gmx.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "starcomponent.h"
8
9#include "binfilehelper.h"
10#include "deepstarcomponent.h"
11#include "highpmstarlist.h"
12#ifndef KSTARS_LITE
13#include "kstars.h"
14#endif
15#include "kstarsdata.h"
16#include "kstarssplash.h"
17#include "Options.h"
18#include "skylabeler.h"
19#include "skymap.h"
20#include "skymesh.h"
21#ifndef KSTARS_LITE
22#include "skyqpainter.h"
23#endif
24#include "htmesh/MeshIterator.h"
25#include "projections/projector.h"
26
27#include "kstars_debug.h"
28
29#include <qplatformdefs.h>
30
31#ifdef _WIN32
32#include <windows.h>
33#endif
34
35#if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
36#include <sys/endian.h>
37#define bswap_16(x) bswap16(x)
38#define bswap_32(x) bswap32(x)
39#else
40#include "byteorder.h"
41#endif
42
43// Qt version calming
44#include <qtskipemptyparts.h>
45
46StarComponent *StarComponent::pinstance = nullptr;
47
48StarComponent::StarComponent(SkyComposite *parent)
49 : ListComponent(parent), m_reindexNum(J2000)
50{
51 m_skyMesh = SkyMesh::Instance();
52 m_StarBlockFactory = StarBlockFactory::Instance();
53
54 m_starIndex.reset(new StarIndex());
55 for (int i = 0; i < m_skyMesh->size(); i++)
56 m_starIndex->append(new StarList());
57 m_highPMStars.append(new HighPMStarList(840.0));
58 m_highPMStars.append(new HighPMStarList(304.0));
59 m_reindexInterval = StarObject::reindexInterval(304.0);
60
61 for (int i = 0; i <= MAX_LINENUMBER_MAG; i++)
62 m_labelList[i] = new LabelList;
63
64 // Actually load data
65 emitProgressText(i18n("Loading stars"));
66
67 loadStaticData();
68 // Load any deep star catalogs that are available
69 loadDeepStarCatalogs();
70
71 // The following works but can cause crashes sometimes
72 //QtConcurrent::run(this, &StarComponent::loadDeepStarCatalogs);
73
74 //In KStars Lite star images are initialized in SkyMapLite
75#ifndef KSTARS_LITE
77#endif
78}
79
80StarComponent::~StarComponent()
81{
82 qDeleteAll(*m_starIndex);
83 m_starIndex->clear();
84 qDeleteAll(m_DeepStarComponents);
85 m_DeepStarComponents.clear();
86 qDeleteAll(m_highPMStars);
87 m_highPMStars.clear();
88 for (int i = 0; i <= MAX_LINENUMBER_MAG; i++)
89 delete m_labelList[i];
90}
91
93{
94 delete pinstance;
95 pinstance = new StarComponent(parent);
96 return pinstance;
97}
98
100{
101 return Options::showStars();
102}
103
104bool StarComponent::addDeepStarCatalogIfExists(const QString &fileName, float trigMag, bool staticstars)
105{
106 if (BinFileHelper::testFileExists(fileName))
107 {
108 m_DeepStarComponents.append(new DeepStarComponent(parent(), fileName, trigMag, staticstars));
109 return true;
110 }
111 return false;
112}
113
114int StarComponent::loadDeepStarCatalogs()
115{
116 // Look for the basic unnamed star catalog to mag 8.0
117 if (!addDeepStarCatalogIfExists("unnamedstars.dat", -5.0, true))
118 return 0;
119
120 // Look for the Tycho-2 add-on with 2.5 million stars to mag 12.5
121 if (!addDeepStarCatalogIfExists("tycho2.dat", 8.0) && !addDeepStarCatalogIfExists("deepstars.dat", 8.0))
122 return 1;
123
124 // Look for the USNO NOMAD 1e8 star catalog add-on with stars to mag 16
125 if (!addDeepStarCatalogIfExists("USNO-NOMAD-1e8.dat", 11.0))
126 return 2;
127
128 return 3;
129}
130
131//This function is empty for a reason; we override the normal
132//update function in favor of JiT updates for stars.
136
137// We use the update hook to re-index all the stars when the date has changed by
138// more than 150 years.
139
140bool StarComponent::reindex(KSNumbers *num)
141{
142 if (!num)
143 return false;
144
145 // for large time steps we re-index all points
146 if (fabs(num->julianCenturies() - m_reindexNum.julianCenturies()) > m_reindexInterval)
147 {
148 reindexAll(num);
149 return true;
150 }
151
152 bool highPM = true;
153
154 // otherwise we just re-index fast movers as needed
155 for (auto &star : m_highPMStars)
156 highPM &= !(star->reindex(num, m_starIndex.get()));
157
158 return !(highPM);
159}
160
161void StarComponent::reindexAll(KSNumbers *num)
162{
163#if 0
164 if (0 && !m_reindexSplash)
165 {
166 m_reindexSplash = new KStarsSplash(i18n("Please wait while re-indexing stars..."));
167 QObject::connect(KStarsData::Instance(), SIGNAL(progressText(QString)), m_reindexSplash,
168 SLOT(setMessage(QString)));
169
170 m_reindexSplash->show();
171 m_reindexSplash->raise();
172 return;
173 }
174#endif
175
176 qCInfo(KSTARS) << "Re-indexing Stars to year" << 2000.0 + num->julianCenturies() * 100.0;
177
178 m_reindexNum = KSNumbers(*num);
179 m_skyMesh->setKSNumbers(num);
180
181 // clear out the old index
182 for (auto &item : *m_starIndex)
183 {
184 item->clear();
185 }
186
187 // re-populate it from the objectList
188 for (auto &object : m_ObjectList)
189 {
190 StarObject *star = dynamic_cast<StarObject *>(object);
191 Trixel trixel = m_skyMesh->indexStar(star);
192
193 m_starIndex->at(trixel)->append(star);
194 }
195
196 // Let everyone else know we have re-indexed to num
197 for (auto &star : m_highPMStars)
198 {
199 star->setIndexTime(num);
200 }
201
202 //delete m_reindexSplash;
203 //m_reindexSplash = 0;
204}
205
206float StarComponent::faintMagnitude() const
207{
208 float faintmag = m_FaintMagnitude;
209
210 for (auto &component : m_DeepStarComponents)
211 {
212 if (faintmag < component->faintMagnitude())
213 faintmag = component->faintMagnitude();
214 }
215 return faintmag;
216}
217
218float StarComponent::zoomMagnitudeLimit()
219{
220 //adjust maglimit for ZoomLevel
221 double lgmin = log10(MINZOOM);
222 double lgz = log10(Options::zoomFactor());
223
224 // Old formula:
225 // float maglim = ( 2.000 + 2.444 * Options::memUsage() / 10.0 ) * ( lgz - lgmin ) + Options::magLimitDrawStarZoomOut();
226
227 /*
228 Explanation for the following formula:
229 --------------------------------------
230 Estimates from a sample of 125000 stars shows that, magnitude
231 limit vs. number of stars follows the formula:
232 nStars = 10^(.45 * maglim + .95)
233 (A better formula is available here: https://www.aa.quae.nl/en/antwoorden/magnituden.html
234 which we do not implement for simplicity)
235 We want to keep the star density on screen a constant. This is directly proportional to the number of stars
236 and directly proportional to the area on screen. The area is in turn inversely proportional to the square
237 of the zoom factor ( zoomFactor / MINZOOM ). This means that (taking logarithms):
238 0.45 * maglim + 0.95 - 2 * log( ZoomFactor ) - log( Star Density ) - log( Some proportionality constant )
239 hence the formula. We've gathered together all the constants and set it to 3.5, so as to set the minimum
240 possible value of maglim to 3.5
241 */
242
243 // float maglim = 4.444 * ( lgz - lgmin ) + 2.222 * log10( Options::starDensity() ) + 3.5;
244
245 // Reducing the slope w.r.t zoom factor to avoid the extremely fast increase in star density with zoom
246 // that 4.444 gives us (although that is what the derivation gives us)
247
248 return 3.5 + 3.7 * (lgz - lgmin) + 2.222 * log10(static_cast<float>(Options::starDensity()));
249}
250
252{
253#ifndef KSTARS_LITE
254 if (!selected())
255 return;
256
257 // If we are displaying HIPS, the it may not make sense to also render stars.
258 if (Options::showHIPS() && !Options::showStarsOverHIPS())
259 return;
260
261 SkyMap *map = SkyMap::Instance();
262 const Projector *proj = map->projector();
263 KStarsData *data = KStarsData::Instance();
264 UpdateID updateID = data->updateID();
265
266 bool checkSlewing = (map->isSlewing() && Options::hideOnSlew());
267 m_hideLabels = checkSlewing || !(Options::showStarMagnitudes() || Options::showStarNames());
268
269 //shortcuts to inform whether to draw different objects
270 bool hideFaintStars = checkSlewing && Options::hideStars();
271 double hideStarsMag = Options::magLimitHideStar();
272 reindex(data->updateNum());
273
274 double lgmin = log10(MINZOOM);
275 double lgmax = log10(MAXZOOM);
276 double lgz = log10(Options::zoomFactor());
277
278 double maglim;
279 m_zoomMagLimit = maglim = zoomMagnitudeLimit();
280
281 double labelMagLim = Options::starLabelDensity() / 5.0;
282 labelMagLim += (12.0 - labelMagLim) * (lgz - lgmin) / (lgmax - lgmin);
283 if (labelMagLim > 8.0)
284 labelMagLim = 8.0;
285
286 //Calculate sizeMagLim
287 // Old formula:
288 // float sizeMagLim = ( 2.000 + 2.444 * Options::memUsage() / 10.0 ) * ( lgz - lgmin ) + 5.8;
289
290 // Using the maglim to compute the sizes of stars reduces
291 // discernability between brighter and fainter stars at high zoom
292 // levels. To fix that, we use an "arbitrary" constant in place of
293 // the variable star density.
294 // Not using this formula now.
295 // float sizeMagLim = 4.444 * ( lgz - lgmin ) + 5.0;
296
297 float sizeMagLim = zoomMagnitudeLimit();
298 if (sizeMagLim > faintMagnitude() * (1 - 1.5 / 16))
299 sizeMagLim = faintMagnitude() * (1 - 1.5 / 16);
300 skyp->setSizeMagLimit(sizeMagLim);
301
302 //Loop for drawing star images
303
304 MeshIterator region(m_skyMesh, DRAW_BUF);
305 magLim = maglim;
306
307 // If we are hiding faint stars, then maglim is really the brighter of hideStarsMag and maglim
308 if (hideFaintStars && maglim > hideStarsMag)
309 maglim = hideStarsMag;
310
311 m_StarBlockFactory->drawID = m_skyMesh->drawID();
312
313 int nTrixels = 0;
314
315 while (region.hasNext())
316 {
317 ++nTrixels;
318 Trixel currentRegion = region.next();
319 StarList *starList = m_starIndex->at(currentRegion);
320
321 for (auto &star : *starList)
322 {
323 if (!star)
324 continue;
325
326 float mag = star->mag();
327
328 // break loop if maglim is reached
329 if (mag > maglim)
330 break;
331
332 if (star->updateID != updateID)
333 star->JITupdate();
334
335 bool drawn = skyp->drawPointSource(star, mag, star->spchar());
336
337 //FIXME_SKYPAINTER: find a better way to do this.
338 if (drawn && !(m_hideLabels || mag > labelMagLim))
339 addLabel(proj->toScreen(star), star);
340 }
341 }
342
343 // Draw focusStar if not null
344 if (focusStar)
345 {
346 if (focusStar->updateID != updateID)
347 focusStar->JITupdate();
348 float mag = focusStar->mag();
349 skyp->drawPointSource(focusStar, mag, focusStar->spchar());
350 }
351
352 // Now draw each of our DeepStarComponents
353 for (auto &component : m_DeepStarComponents)
354 {
355 component->draw(skyp);
356 }
357#else
358 Q_UNUSED(skyp)
359#endif
360}
361
362void StarComponent::addLabel(const QPointF &p, StarObject *star)
363{
364 int idx = int(star->mag() * 10.0);
365 if (idx < 0)
366 idx = 0;
367 if (idx > MAX_LINENUMBER_MAG)
368 idx = MAX_LINENUMBER_MAG;
369 m_labelList[idx]->append(SkyLabel(p, star));
370}
371
373{
374 if (m_hideLabels)
375 return;
376
377 SkyLabeler *labeler = SkyLabeler::Instance();
378 labeler->setPen(QColor(KStarsData::Instance()->colorScheme()->colorNamed("SNameColor")));
379
380 int max = int(m_zoomMagLimit * 10.0);
381 if (max < 0)
382 max = 0;
383 if (max > MAX_LINENUMBER_MAG)
384 max = MAX_LINENUMBER_MAG;
385
386 for (int i = 0; i <= max; i++)
387 {
388 LabelList *list = m_labelList[i];
389
390 for (const auto &item : *list)
391 {
392 labeler->drawNameLabel(item.obj, item.o);
393 }
394 list->clear();
395 }
396}
397
398bool StarComponent::loadStaticData()
399{
400 // We break from Qt / KDE API and use traditional file handling here, to obtain speed.
401 // We also avoid C++ constructors for the same reason.
402 FILE *dataFile, *nameFile;
403 bool swapBytes = false, named = false, gnamed = false;
404 BinFileHelper dataReader, nameReader;
405 QString name, gname, visibleName;
406 StarObject *star;
407
408 if (starsLoaded)
409 return true;
410
411 // prepare to index stars to this date
412 m_skyMesh->setKSNumbers(&m_reindexNum);
413
414 /* Open the data files */
415 // TODO: Maybe we don't want to hardcode the filename?
416 if ((dataFile = dataReader.openFile("namedstars.dat")) == nullptr)
417 {
418 qCWarning(KSTARS) << "Could not open data file namedstars.dat";
419 return false;
420 }
421
422 if (!(nameFile = nameReader.openFile("starnames.dat")))
423 {
424 qCWarning(KSTARS) << "Could not open data file starnames.dat";
425 return false;
426 }
427
428 if (!dataReader.readHeader())
429 {
430 qCWarning(KSTARS) << "Error reading namedstars.dat header : " << dataReader.getErrorNumber() << " : "
431 << dataReader.getError();
432 return false;
433 }
434
435 if (!nameReader.readHeader())
436 {
437 qCWarning(KSTARS) << "Error reading starnames.dat header : " << nameReader.getErrorNumber() << " : "
438 << nameReader.getError();
439 return false;
440 }
441 //KDE_fseek(nameFile, nameReader.getDataOffset(), SEEK_SET);
442 QT_FSEEK(nameFile, nameReader.getDataOffset(), SEEK_SET);
443 swapBytes = dataReader.getByteSwap();
444
445 long int nstars = 0;
446
447 //KDE_fseek(dataFile, dataReader.getDataOffset(), SEEK_SET);
448 QT_FSEEK(dataFile, dataReader.getDataOffset(), SEEK_SET);
449
450 qint16 faintmag;
451 quint8 htm_level;
452 quint16 t_MSpT;
453 int ret = 0;
454
455 // Faint Magnitude
456 ret = fread(&faintmag, 2, 1, dataFile);
457 if (swapBytes)
458 faintmag = bswap_16(faintmag);
459
460 // HTM Level
461 ret = fread(&htm_level, 1, 1, dataFile);
462
463 // Unused
464 {
465 int rc = fread(&t_MSpT, 2, 1, dataFile);
466 Q_UNUSED(rc)
467 }
468
469 if (faintmag / 100.0 > m_FaintMagnitude)
470 m_FaintMagnitude = faintmag / 100.0;
471
472 if (htm_level != m_skyMesh->level())
473 qCWarning(KSTARS)
474 << "HTM Level in shallow star data file and HTM Level in m_skyMesh do not match. EXPECT TROUBLE"
475 ;
476 for (int i = 0; i < m_skyMesh->size(); ++i)
477 {
478 Trixel trixel = i; // = ( ( i >= 256 ) ? ( i - 256 ) : ( i + 256 ) );
479 for (unsigned long j = 0; j < static_cast<unsigned long>(dataReader.getRecordCount(i)); ++j)
480 {
481 if (1 != fread(&stardata, sizeof(StarData), 1, dataFile))
482 {
483 qCCritical(KSTARS) << "FILE FORMAT ERROR: Could not read StarData structure for star #" << j << " under trixel #"
484 << trixel;
485 continue;
486 }
487
488 /* Swap Bytes when required */
489 if (swapBytes)
490 byteSwap(&stardata);
491
492 named = false;
493 gnamed = false;
494
495 /* Named Star - Read the nameFile */
496 if (stardata.flags & 0x01)
497 {
498 visibleName = "";
499 if (1 != fread(&starname, sizeof(starName), 1, nameFile))
500 qCCritical(KSTARS) << "ERROR: fread() call on nameFile failed in trixel " << trixel << " star " << j;
501
502 name = QString::fromLatin1(starname.longName);
503 named = !name.isEmpty();
504
505 gname = QString::fromLatin1(starname.bayerName);
506 gnamed = !gname.isEmpty();
507
508 if (gnamed && starname.bayerName[0] != '.')
509 visibleName = gname;
510
511 if (named)
512 {
513 // HEV: look up star name in internationalization filesource
514 name = i18nc("star name", name.toLocal8Bit().data());
515 }
516 else
517 {
518 name = i18n("star");
519 }
520 }
521 else
522 qCCritical(KSTARS) << "ERROR: Named star file contains unnamed stars! Expect trouble.";
523
524 /* Create the new StarObject */
525 star = new StarObject;
526 star->init(&stardata);
527 //if( star->getHDIndex() != 0 && name == i18n("star"))
528 if (stardata.HD)
529 {
530 m_HDHash.insert(stardata.HD, star);
531 if (named == false)
532 {
533 name = QString("HD %1").arg(stardata.HD);
534 named = true;
535 }
536 }
537
538 star->setNames(name, visibleName);
539 //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
540 ++nstars;
541
542 if (gnamed)
543 m_genName.insert(gname, star);
544
545 //if ( ! name.isEmpty() && name != i18n("star"))
546 if (named)
547 {
548 objectNames(SkyObject::STAR).append(name);
549 objectLists(SkyObject::STAR).append(QPair<QString, const SkyObject *>(name, star));
550 }
551
552 if (!visibleName.isEmpty() && gname != name)
553 {
554 QString gName = star->gname(false);
555 objectNames(SkyObject::STAR).append(gName);
556 objectLists(SkyObject::STAR).append(QPair<QString, const SkyObject *>(gName, star));
557 }
558
559 appendListObject(star);
560
561 m_starIndex->at(trixel)->append(star);
562 double pm = star->pmMagnitude();
563
564 for (auto &list : m_highPMStars)
565 {
566 if (list->append(trixel, star, pm))
567 break;
568 }
569 }
570 }
571
572 dataReader.closeFile();
573 nameReader.closeFile();
574
575 starsLoaded = true;
576 return true;
577}
578
580{
581 m_ObjectList.append(object);
582 m_ObjectHash.insert(object->name().toLower(), object);
583 m_ObjectHash.insert(object->longname().toLower(), object);
584 m_ObjectHash.insert(object->name2().toLower(), object);
585 m_ObjectHash.insert(object->name2().toLower(), object);
586 m_ObjectHash.insert((dynamic_cast<StarObject *>(object))->gname(false).toLower(), object);
587}
588
589SkyObject *StarComponent::findStarByGenetiveName(const QString name)
590{
591 if (name.startsWith(QLatin1String("HD")))
592 {
593 QStringList fields = name.split(' ', Qt::SkipEmptyParts);
594 bool Ok = false;
595 unsigned int HDNum = fields[1].toInt(&Ok);
596 if (Ok)
597 return findByHDIndex(HDNum);
598 }
599 return m_genName.value(name);
600}
601
603{
604 for (SkyRegion::const_iterator it = region.constBegin(); it != region.constEnd(); ++it)
605 {
606 Trixel trixel = it.key();
607 StarList *starlist = m_starIndex->at(trixel);
608 for (int i = 0; starlist && i < starlist->size(); i++)
609 if (starlist->at(i) && starlist->at(i)->name() != QString("star"))
610 list.push_back(starlist->at(i));
611 }
612}
613
615{
616 KStarsData *data = KStarsData::Instance();
617 StarObject *o = nullptr;
618 BinFileHelper hdidxReader;
619
620 // First check the hash to see if we have a corresponding StarObject already
621 if ((o = m_HDHash.value(HDnum, nullptr)))
622 return o;
623 // If we don't have the StarObject here, try it in the DeepStarComponents' hashes
624 if (m_DeepStarComponents.size() >= 1)
625 if ((o = m_DeepStarComponents.at(0)->findByHDIndex(HDnum)))
626 return o;
627 if (m_DeepStarComponents.size() >= 2)
628 {
629 qint32 offset = 0;
630 int ret = 0;
631 FILE *hdidxFile = hdidxReader.openFile("Henry-Draper.idx");
632 FILE *dataFile = nullptr;
633
634 if (!hdidxFile)
635 return nullptr;
636 //KDE_fseek( hdidxFile, (HDnum - 1) * 4, SEEK_SET );
637 QT_FSEEK(hdidxFile, (HDnum - 1) * 4, SEEK_SET);
638 // TODO: Offsets need to be byteswapped if this is a big endian machine.
639 // This means that the Henry Draper Index needs a endianness indicator.
640 ret = fread(&offset, 4, 1, hdidxFile);
641 if (offset <= 0)
642 return nullptr;
643 dataFile = m_DeepStarComponents.at(1)->getStarReader()->getFileHandle();
644 //KDE_fseek( dataFile, offset, SEEK_SET );
645 QT_FSEEK(dataFile, offset, SEEK_SET);
646 {
647 int rc = fread(&stardata, sizeof(StarData), 1, dataFile);
648 Q_UNUSED(rc)
649 }
650 if (m_DeepStarComponents.at(1)->getStarReader()->getByteSwap())
651 {
652 byteSwap(&stardata);
653 }
654 m_starObject.init(&stardata);
655 m_starObject.EquatorialToHorizontal(data->lst(), data->geo()->lat());
656 m_starObject.JITupdate();
657 focusStar = m_starObject.clone();
658 m_HDHash.insert(HDnum, focusStar);
659 hdidxReader.closeFile();
660 return focusStar;
661 }
662
663 return nullptr;
664}
665
666// This uses the main star index for looking up nearby stars but then
667// filters out objects with the generic name "star". We could easily
668// build an index for just the named stars which would make this go
669// much faster still. -jbb
670//
671SkyObject *StarComponent::objectNearest(SkyPoint *p, double &maxrad)
672{
673 m_zoomMagLimit = zoomMagnitudeLimit();
674
675 SkyObject *oBest = nullptr;
676
677 MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF);
678
679 while (region.hasNext())
680 {
681 Trixel currentRegion = region.next();
682 StarList *starList = m_starIndex->at(currentRegion);
683
684 for (auto &star : *starList)
685 {
686 if (!star)
687 continue;
688 if (star->mag() > m_zoomMagLimit)
689 continue;
690
691 double r = star->angularDistanceTo(p).Degrees();
692
693 if (r < maxrad)
694 {
695 oBest = star;
696 maxrad = r;
697 }
698 }
699 }
700
701 // Check up with our Deep Star Components too!
702 double rTry, rBest;
703 SkyObject *oTry;
704 // JM 2016-03-30: Multiply rBest by a factor of 0.5 so that named stars are preferred to unnamed stars searched below
705 rBest = maxrad * 0.5;
706 rTry = maxrad;
707 for (auto &component : m_DeepStarComponents)
708 {
709 oTry = component->objectNearest(p, rTry);
710 if (rTry < rBest)
711 {
712 rBest = rTry;
713 oBest = oTry;
714 }
715 }
716 maxrad = rBest;
717
718 return oBest;
719}
720
721void StarComponent::starsInAperture(QList<StarObject *> &list, const SkyPoint &center, float radius, float maglim)
722{
723 // Ensure that we have deprecessed the (RA, Dec) to (RA0, Dec0)
724 Q_ASSERT(center.ra0().Degrees() >= 0.0);
725 Q_ASSERT(center.dec0().Degrees() <= 90.0);
726
727 m_skyMesh->intersect(center.ra0().Degrees(), center.dec0().Degrees(), radius, static_cast<BufNum>(OBJ_NEAREST_BUF));
728
729 MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF);
730
731 if (maglim < -28)
732 maglim = m_FaintMagnitude;
733
734 while (region.hasNext())
735 {
736 Trixel currentRegion = region.next();
737 StarList *starList = m_starIndex->at(currentRegion);
738
739 for (auto &star : *starList)
740 {
741 if (!star)
742 continue;
743 if (star->mag() > m_FaintMagnitude)
744 continue;
745 if (star->angularDistanceTo(&center).Degrees() <= radius)
746 list.append(star);
747 }
748 }
749
750 // Add stars from the DeepStarComponents as well
751 for (auto &component : m_DeepStarComponents)
752 {
753 component->starsInAperture(list, center, radius, maglim);
754 }
755}
756
757void StarComponent::byteSwap(StarData *stardata)
758{
759 stardata->RA = bswap_32(stardata->RA);
760 stardata->Dec = bswap_32(stardata->Dec);
761 stardata->dRA = bswap_32(stardata->dRA);
762 stardata->dDec = bswap_32(stardata->dDec);
763 stardata->parallax = bswap_32(stardata->parallax);
764 stardata->HD = bswap_32(stardata->HD);
765 stardata->mag = bswap_16(stardata->mag);
766 stardata->bv_index = bswap_16(stardata->bv_index);
767}
768/*
769void StarComponent::printDebugInfo() {
770
771 int nTrixels = 0;
772 int nBlocks = 0;
773 long int nStars = 0;
774 float faintMag = -5.0;
775
776 MeshIterator trixels( m_skyMesh, DRAW_BUF );
777 Trixel trixel;
778
779 while( trixels.hasNext() ) {
780 trixel = trixels.next();
781 nTrixels++;
782 for(int i = 0; i < m_starBlockList[ trixel ]->getBlockCount(); ++i) {
783 nBlocks++;
784 StarBlock *block = m_starBlockList[ trixel ]->block( i );
785 for(int j = 0; j < block->getStarCount(); ++j) {
786 nStars++;
787 }
788 if( block->getFaintMag() > faintMag ) {
789 faintMag = block->getFaintMag();
790 }
791 }
792 }
793
794 printf( "========== UNNAMED STAR MEMORY ALLOCATION INFORMATION ==========\n" );
795 printf( "Number of visible trixels = %8d\n", nTrixels );
796 printf( "Number of visible StarBlocks = %8d\n", nBlocks );
797 printf( "Number of StarBlocks allocated via SBF = %8d\n", m_StarBlockFactory.getBlockCount() );
798 printf( "Number of unnamed stars in memory = %8ld\n", nStars );
799 printf( "Magnitude of the faintest star in memory = %8.2f\n", faintMag );
800 printf( "Target magnitude limit = %8.2f\n", magLim );
801 printf( "Size of each StarBlock = %8d bytes\n", sizeof( StarBlock ) );
802 printf( "Size of each StarObject = %8d bytes\n", sizeof( StarObject ) );
803 printf( "Memory use due to visible unnamed stars = %8.2f MB\n", ( sizeof( StarObject ) * nStars / 1048576.0 ) );
804 printf( "Memory use due to visible StarBlocks = %8d bytes\n", sizeof( StarBlock ) * nBlocks );
805 printf( "Memory use due to StarBlocks in SBF = %8d bytes\n", sizeof( StarBlock ) * m_StarBlockFactory.getBlockCount() );
806 printf( "=============== STAR DRAW LOOP TIMING INFORMATION ==============\n" );
807 printf( "Time taken for drawing named stars = %8ld ms\n", t_drawNamed );
808 printf( "Time taken for dynamic load of data = %8ld ms\n", t_dynamicLoad );
809 printf( "Time taken for updating LRU cache = %8ld ms\n", t_updateCache );
810 printf( "Time taken for drawing unnamed stars = %8ld ms\n", t_drawUnnamed );
811 printf( "================================================================\n" );
812}
813
814bool StarComponent::verifySBLIntegrity() {
815
816 float faintMag = -5.0;
817 bool integrity = true;
818 for(Trixel trixel = 0; trixel < m_skyMesh->size(); ++trixel) {
819 for(int i = 0; i < m_starBlockList[ trixel ]->getBlockCount(); ++i) {
820 StarBlock *block = m_starBlockList[ trixel ]->block( i );
821 if( i == 0 )
822 faintMag = block->getBrightMag();
823 // NOTE: Assumes 2 decimal places in magnitude field. TODO: Change if it ever does change
824 if( block->getBrightMag() != faintMag && ( block->getBrightMag() - faintMag ) > 0.016) {
825 qDebug() << Q_FUNC_INFO << "Trixel " << trixel << ": ERROR: faintMag of prev block = " << faintMag
826 << ", brightMag of block #" << i << " = " << block->getBrightMag();
827 integrity = false;
828 }
829 if( i > 1 && ( !block->prev ) )
830 qDebug() << Q_FUNC_INFO << "Trixel " << trixel << ": ERROR: Block" << i << "is unlinked in LRU Cache";
831 if( block->prev && block->prev->parent == m_starBlockList[ trixel ]
832 && block->prev != m_starBlockList[ trixel ]->block( i - 1 ) ) {
833 qDebug() << Q_FUNC_INFO << "Trixel " << trixel << ": ERROR: SBF LRU Cache linked list seems to be broken at before block " << i;
834 integrity = false;
835 }
836 faintMag = block->getFaintMag();
837 }
838 }
839 return integrity;
840}
841*/
This class provides utility functions to handle binary data files in the format prescribed by KStars.
static bool testFileExists(const QString &fileName)
Checks if a file exists.
long getDataOffset() const
Returns the offset at which the data begins.
void closeFile()
Close the binary data file.
bool readHeader()
Read the header and index table from the file and fill up the QVector s with the entries.
int getErrorNumber()
Get error number.
bool getByteSwap() const
Should we do byte swapping?
unsigned int getRecordCount(int id) const
Returns the number of records under the given index ID.
FILE * openFile(const QString &fileName)
WARNING: This function may not be compatible in other locales, because it calls QString::toAscii.
QString getError()
Get error string.
Stores and manages unnamed stars, most of which are dynamically loaded into memory.
const CachingDms * lat() const
Definition geolocation.h:70
int size() const
returns the total number of trixels in the HTM.
Definition HTMesh.h:118
int level() const
returns the mesh level.
Definition HTMesh.h:122
void intersect(double ra, double dec, double radius, BufNum bufNum=0)
NOTE: The intersect() routines below are all used to find the trixels needed to cover a geometric obj...
Definition HTMesh.cpp:104
Holds a list of stars with high proper motion along with the trixel each star is currently located in...
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
double julianCenturies() const
Definition ksnumbers.h:88
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:226
GeoLocation * geo()
Definition kstarsdata.h:232
The KStars Splash Screen.
An abstract parent class, to be inherited by SkyComponents that store a QList of SkyObjects.
MeshIterator is a very lightweight class used to iterate over the result set of an HTMesh intersectio...
Trixel next() const
returns the next trixel
bool hasNext() const
true if there are more trixel to iterate over.
The Projector class is the primary class that serves as an interface to handle projections.
Definition projector.h:58
QPointF toScreen(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
This is exactly the same as toScreenVec but it returns a QPointF.
Definition projector.cpp:93
SkyComposite * parent()
SkyComposite is a kind of container class for SkyComponent objects.
The purpose of this class is to prevent labels from overlapping.
Definition skylabeler.h:99
void setPen(const QPen &pen)
sets the pen used for drawing labels on the sky.
bool drawNameLabel(SkyObject *obj, const QPointF &_p, const qreal padding_factor=1)
Tries to draw a label for an object.
This is the canvas on which the sky is painted.
Definition skymap.h:54
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition skymesh.cpp:39
DrawID drawID() const
Definition skymesh.h:264
void setKSNumbers(KSNumbers *num)
sets the time for indexing StarObjects and CLines.
Definition skymesh.h:145
Trixel indexStar(StarObject *star)
returns the trixel that contains the star at the set time with proper motion taken into account but n...
Definition skymesh.cpp:79
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:146
virtual QString longname(void) const
Definition skyobject.h:165
QString name2(void) const
Definition skyobject.h:157
float mag() const
Definition skyobject.h:207
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
virtual bool drawPointSource(const SkyPoint *loc, float mag, char sp='A')=0
Draw a point source (e.g., a star).
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
Definition skypoint.cpp:899
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition skypoint.cpp:77
static void initStarImages()
Recalculates the star pixmaps.
Represents the stars on the sky map.
void update(KSNumbers *num) override
Update the sky positions of this component.
bool selected() override
void draw(SkyPainter *skyp) override
Draw the object on the SkyMap skyp a pointer to the SkyPainter to use.
void starsInAperture(QList< StarObject * > &list, const SkyPoint &center, float radius, float maglim=-29)
Add to the given list, the stars from this component, that lie within the specified circular aperture...
StarObject * findByHDIndex(int HDnum)
Find stars by HD catalog index.
SkyObject * objectNearest(SkyPoint *p, double &maxrad) override
Find the SkyObject nearest the given SkyPoint.
void appendListObject(SkyObject *object)
Append a star to the Object List.
static StarComponent * Create(SkyComposite *)
Create an instance of StarComponent.
void drawLabels()
draw all the labels in the prioritized LabelLists and then clear the LabelLists.
void objectsInArea(QList< SkyObject * > &list, const SkyRegion &region) override
Searches the region(s) and appends the SkyObjects found to the list of sky objects.
This is a subclass of SkyObject.
Definition starobject.h:33
static double reindexInterval(double pm)
returns the reindex interval (in centuries!) for the given magnitude of proper motion (in milliarcsec...
StarObject * clone() const override
Create copy of object.
void JITupdate()
added for JIT updates from both StarComponent and ConstellationLines
void setNames(const QString &name, const QString &name2)
Sets the name, genetive name, and long name.
char spchar() const
Returns just the first character of the spectral type string.
double pmMagnitude() const
returns the magnitude of the proper motion correction in milliarcsec/year
Definition starobject.h:199
void init(const StarData *stardata)
Initializes a StarObject to given data.
QString gname(bool useGreekChars=true) const
Returns the genetive name of the star.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString name(StandardAction id)
char * data()
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator insert(const Key &key, const T &value)
T value(const Key &key) const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
void push_back(parameter_type value)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QByteArray toLocal8Bit() const const
QString toLower() const const
SkipEmptyParts
void raise()
void show()
A 32-byte Structure that holds star data.
Definition stardata.h:18
qint16 mag
signed 16-bit raw magnitude.
Definition stardata.h:25
qint32 RA
Raw signed 32-bit RA value.
Definition stardata.h:19
qint32 HD
unsigned 32-bit Henry Draper Index.
Definition stardata.h:24
qint32 Dec
Raw signed 32-bit DE value.
Definition stardata.h:20
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.