Kstars

deepstarcomponent.cpp
1 /*
2  SPDX-FileCopyrightText: 2008 Akarsh Simha Thomas Kabelmann <[email protected], [email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "deepstarcomponent.h"
8 
9 #include "byteorder.h"
10 #include "kstarsdata.h"
11 #include "Options.h"
12 #ifndef KSTARS_LITE
13 #include "skymap.h"
14 #endif
15 #include "skymesh.h"
16 #include "skypainter.h"
17 #include "starblock.h"
18 #include "starcomponent.h"
19 #include "htmesh/MeshIterator.h"
20 #include "projections/projector.h"
21 
22 #include <qplatformdefs.h>
23 #include <QtConcurrent>
24 #include <QElapsedTimer>
25 
26 #include <kstars_debug.h>
27 
28 #ifdef _WIN32
29 #include <windows.h>
30 #endif
31 
32 DeepStarComponent::DeepStarComponent(SkyComposite *parent, QString fileName, float trigMag, bool staticstars)
33  : ListComponent(parent), m_reindexNum(J2000), triggerMag(trigMag), m_FaintMagnitude(-5.0), staticStars(staticstars),
34  dataFileName(fileName)
35 {
36  fileOpened = false;
37  openDataFile();
38  if (staticStars)
39  loadStaticStars();
40  qCInfo(KSTARS) << "Loaded DSO catalog file: " << dataFileName;
41 }
42 
43 DeepStarComponent::~DeepStarComponent()
44 {
45  if (fileOpened)
46  starReader.closeFile();
47  fileOpened = false;
48 }
49 
50 bool DeepStarComponent::loadStaticStars()
51 {
52  FILE *dataFile;
53 
54  if (!staticStars)
55  return true;
56  if (!fileOpened)
57  return false;
58 
59  dataFile = starReader.getFileHandle();
60  rewind(dataFile);
61 
62  if (!starReader.readHeader())
63  {
64  qCCritical(KSTARS) << "Error reading header of catalog file " << dataFileName << ": " << starReader.getErrorNumber()
65  << ": " << starReader.getError();
66  return false;
67  }
68 
69  quint8 recordSize = starReader.guessRecordSize();
70 
71  if (recordSize != 16 && recordSize != 32)
72  {
73  qCCritical(KSTARS) << "Cannot understand catalog file " << dataFileName;
74  return false;
75  }
76 
77  //KDE_fseek(dataFile, starReader.getDataOffset(), SEEK_SET);
78  QT_FSEEK(dataFile, starReader.getDataOffset(), SEEK_SET);
79 
80  qint16 faintmag;
81  quint8 htm_level;
82  quint16 t_MSpT;
83  int ret = 0;
84 
85  ret = fread(&faintmag, 2, 1, dataFile);
86  if (starReader.getByteSwap())
87  faintmag = bswap_16(faintmag);
88  ret = fread(&htm_level, 1, 1, dataFile);
89  ret = fread(&t_MSpT, 2, 1, dataFile); // Unused
90  if (starReader.getByteSwap())
91  faintmag = bswap_16(faintmag);
92 
93  // TODO: Read the multiplying factor from the dataFile
94  m_FaintMagnitude = faintmag / 100.0;
95 
96  if (htm_level != m_skyMesh->level())
97  qCWarning(KSTARS) << "HTM Level in shallow star data file and HTM Level in m_skyMesh do not match. EXPECT TROUBLE!";
98 
99  // JM 2012-12-05: Breaking into 2 loops instead of one previously with multiple IF checks for recordSize
100  // While the CPU branch prediction might not suffer any penalties since the branch prediction after a few times
101  // should always gets it right. It's better to do it this way to avoid any chances since the compiler might not optimize it.
102  if (recordSize == 32)
103  {
104  for (Trixel i = 0; i < m_skyMesh->size(); ++i)
105  {
106  Trixel trixel = i;
107  quint64 records = starReader.getRecordCount(i);
108  std::shared_ptr<StarBlock> SB(new StarBlock(records));
109 
110  if (!SB.get())
111  qCCritical(KSTARS) << "ERROR: Could not allocate new StarBlock to hold shallow unnamed stars for trixel "
112  << trixel;
113 
114  m_starBlockList.at(trixel)->setStaticBlock(SB);
115 
116  for (quint64 j = 0; j < records; ++j)
117  {
118  bool fread_success = fread(&stardata, sizeof(StarData), 1, dataFile);
119 
120  if (!fread_success)
121  {
122  qCCritical(KSTARS) << "ERROR: Could not read StarData structure for star #" << j << " under trixel #"
123  << trixel;
124  }
125 
126  /* Swap Bytes when required */
127  if (starReader.getByteSwap())
128  byteSwap(&stardata);
129 
130  /* Initialize star with data just read. */
131  StarObject *star;
132 #ifdef KSTARS_LITE
133  star = &(SB->addStar(stardata)->star);
134 #else
135  star = SB->addStar(stardata);
136 #endif
137  if (star)
138  {
139  //KStarsData* data = KStarsData::Instance();
140  //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
141  //if( star->getHDIndex() != 0 )
142  if (stardata.HD)
143  m_CatalogNumber.insert(stardata.HD, star);
144  }
145  else
146  {
147  qCCritical(KSTARS) << "CODE ERROR: More unnamed static stars in trixel " << trixel
148  << " than we allocated space for!";
149  }
150  }
151  }
152  }
153  else
154  {
155  for (Trixel i = 0; i < m_skyMesh->size(); ++i)
156  {
157  Trixel trixel = i;
158  quint64 records = starReader.getRecordCount(i);
159  std::shared_ptr<StarBlock> SB(new StarBlock(records));
160 
161  if (!SB.get())
162  qCCritical(KSTARS) << "Could not allocate new StarBlock to hold shallow unnamed stars for trixel "
163  << trixel;
164 
165  m_starBlockList.at(trixel)->setStaticBlock(SB);
166 
167  for (quint64 j = 0; j < records; ++j)
168  {
169  bool fread_success = false;
170  fread_success = fread(&deepstardata, sizeof(DeepStarData), 1, dataFile);
171 
172  if (!fread_success)
173  {
174  qCCritical(KSTARS) << "Could not read StarData structure for star #" << j << " under trixel #"
175  << trixel;
176  }
177 
178  /* Swap Bytes when required */
179  if (starReader.getByteSwap())
180  byteSwap(&deepstardata);
181 
182  /* Initialize star with data just read. */
183  StarObject *star;
184 #ifdef KSTARS_LITE
185  star = &(SB->addStar(stardata)->star);
186 #else
187  star = SB->addStar(deepstardata);
188 #endif
189  if (star)
190  {
191  //KStarsData* data = KStarsData::Instance();
192  //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
193  //if( star->getHDIndex() != 0 )
194  if (stardata.HD)
195  m_CatalogNumber.insert(stardata.HD, star);
196  }
197  else
198  {
199  qCCritical(KSTARS) << "CODE ERROR: More unnamed static stars in trixel " << trixel
200  << " than we allocated space for!";
201  }
202  }
203  }
204  }
205 
206  return true;
207 }
208 
210 {
211  return Options::showStars() && fileOpened;
212 }
213 
214 bool openIndexFile()
215 {
216  // TODO: Work out the details
217  /*
218  if( hdidxReader.openFile( "Henry-Draper.idx" ) )
219  qDebug() << Q_FUNC_INFO << "Could not open HD Index file. Search by HD numbers for deep stars will not work.";
220  */
221  return 0;
222 }
223 
224 //This function is empty for a reason; we override the normal
225 //update function in favor of JiT updates for stars.
227 {
228 }
229 
230 // TODO: Optimize draw, if it is worth it.
232 {
233 #ifndef KSTARS_LITE
234  if (!fileOpened)
235  return;
236 
237 #ifdef PROFILE_SINCOS
238  long trig_calls_here = -dms::trig_function_calls;
239  long trig_redundancy_here = -dms::redundant_trig_function_calls;
240  long cachingdms_bad_uses = -CachingDms::cachingdms_bad_uses;
241  dms::seconds_in_trig = 0.;
242 #endif
243 
244 #ifdef PROFILE_UPDATECOORDS
245  StarObject::updateCoordsCpuTime = 0.;
246  StarObject::starsUpdated = 0;
247 #endif
248  SkyMap *map = SkyMap::Instance();
249  KStarsData *data = KStarsData::Instance();
250  UpdateID updateID = data->updateID();
251 
252  //FIXME_FOV -- maybe not clamp like that...
253  float radius = map->projector()->fov();
254  if (radius > 90.0)
255  radius = 90.0;
256 
257  if (m_skyMesh != SkyMesh::Instance() && m_skyMesh->inDraw())
258  {
259  printf("Warning: aborting concurrent DeepStarComponent::draw()");
260  }
261  bool checkSlewing = (map->isSlewing() && Options::hideOnSlew());
262 
263  //shortcuts to inform whether to draw different objects
264  bool hideFaintStars(checkSlewing && Options::hideStars());
265  double hideStarsMag = Options::magLimitHideStar();
266 
267  //adjust maglimit for ZoomLevel
268  // double lgmin = log10(MINZOOM);
269  // double lgmax = log10(MAXZOOM);
270  // double lgz = log10(Options::zoomFactor());
271  // TODO: Enable hiding of faint stars
272 
273  float maglim = StarComponent::zoomMagnitudeLimit();
274 
275  if (maglim < triggerMag)
276  return;
277 
278  m_zoomMagLimit = maglim;
279 
280  m_skyMesh->inDraw(true);
281 
282  SkyPoint *focus = map->focus();
283  m_skyMesh->aperture(focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing
284 
285  MeshIterator region(m_skyMesh, DRAW_BUF);
286 
287  // If we are to hide the fainter stars (eg: while slewing), we set the magnitude limit to hideStarsMag.
288  if (hideFaintStars && maglim > hideStarsMag)
289  maglim = hideStarsMag;
290 
291  StarBlockFactory *m_StarBlockFactory = StarBlockFactory::Instance();
292  // m_StarBlockFactory->drawID = m_skyMesh->drawID();
293  // qDebug() << Q_FUNC_INFO << "Mesh size = " << m_skyMesh->size() << "; drawID = " << m_skyMesh->drawID();
294  QElapsedTimer t;
295  int nTrixels = 0;
296 
297  t_dynamicLoad = 0;
298  t_updateCache = 0;
299  t_drawUnnamed = 0;
300 
301  visibleStarCount = 0;
302 
303  t.start();
304 
305  // Mark used blocks in the LRU Cache. Not required for static stars
306  if (!staticStars)
307  {
308  while (region.hasNext())
309  {
310  Trixel currentRegion = region.next();
311  for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i)
312  {
313  std::shared_ptr<StarBlock> prevBlock = ((i >= 1) ? m_starBlockList.at(currentRegion)->block(
314  i - 1) : std::shared_ptr<StarBlock>());
315  std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i);
316 
317  if (i == 0 && !m_StarBlockFactory->markFirst(block))
318  qCWarning(KSTARS) << "markFirst failed in trixel" << currentRegion;
319  if (i > 0 && !m_StarBlockFactory->markNext(prevBlock, block))
320  qCWarning(KSTARS) << "markNext failed in trixel" << currentRegion << "while marking block" << i;
321  if (i < m_starBlockList.at(currentRegion)->getBlockCount() &&
322  m_starBlockList.at(currentRegion)->block(i)->getFaintMag() < maglim)
323  break;
324  }
325  }
326  t_updateCache = t.elapsed();
327  region.reset();
328  }
329 
330  while (region.hasNext())
331  {
332  ++nTrixels;
333  Trixel currentRegion = region.next();
334 
335  // NOTE: We are guessing that the last 1.5/16 magnitudes in the catalog are just additions and the star catalog
336  // is actually supposed to reach out continuously enough only to mag m_FaintMagnitude * ( 1 - 1.5/16 )
337  // TODO: Is there a better way? We may have to change the magnitude tolerance if the catalog changes
338  // Static stars need not execute fillToMag
339 
340  // Safety check if the current region is in star block list
341  if (currentRegion >= m_starBlockList.size())
342  continue;
343 
344  if (!staticStars)
345  {
346  m_starBlockList.at(currentRegion)->fillToMag(maglim);
347  }
348 
349  // if (!staticStars && !m_starBlockList.at(currentRegion)->fillToMag(maglim) &&
350  // maglim <= m_FaintMagnitude * (1 - 1.5 / 16))
351  // {
352  // qCWarning(KSTARS) << "SBL::fillToMag( " << maglim << " ) failed for trixel " << currentRegion;
353  // }
354 
355  t_dynamicLoad += t.restart();
356 
357  // qDebug() << Q_FUNC_INFO << "Drawing SBL for trixel " << currentRegion << ", SBL has "
358  // << m_starBlockList[ currentRegion ]->getBlockCount() << " blocks";
359 
360  // REMARK: The following should never carry state, except for const parameters like updateID and maglim
361  std::function<void(std::shared_ptr<StarBlock>)> mapFunction = [&updateID, &maglim](std::shared_ptr<StarBlock> myBlock)
362  {
363  for (StarObject &star : myBlock->contents())
364  {
365  if (star.updateID != updateID)
366  star.JITupdate();
367  if (star.mag() > maglim)
368  break;
369  }
370  };
371 
372  QtConcurrent::blockingMap(m_starBlockList.at(currentRegion)->contents(), mapFunction);
373 
374  for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i)
375  {
376  std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i);
377  // qDebug() << Q_FUNC_INFO << "---> Drawing stars from block " << i << " of trixel " <<
378  // currentRegion << ". SB has " << block->getStarCount() << " stars";
379  for (int j = 0; j < block->getStarCount(); j++)
380  {
381  StarObject *curStar = block->star(j);
382 
383  // qDebug() << Q_FUNC_INFO << "We claim that he's from trixel " << currentRegion
384  //<< ", and indexStar says he's from " << m_skyMesh->indexStar( curStar );
385 
386  float mag = curStar->mag();
387 
388  if (mag > maglim)
389  break;
390 
391  if (skyp->drawPointSource(curStar, mag, curStar->spchar()))
392  visibleStarCount++;
393  }
394  }
395 
396  // DEBUG: Uncomment to identify problems with Star Block Factory / preservation of Magnitude Order in the LRU Cache
397  // verifySBLIntegrity();
398  t_drawUnnamed += t.restart();
399  }
400  m_skyMesh->inDraw(false);
401 #ifdef PROFILE_SINCOS
402  trig_calls_here += dms::trig_function_calls;
403  trig_redundancy_here += dms::redundant_trig_function_calls;
404  cachingdms_bad_uses += CachingDms::cachingdms_bad_uses;
405  qDebug() << Q_FUNC_INFO << "Spent " << dms::seconds_in_trig << " seconds doing " << trig_calls_here
406  << " trigonometric function calls amounting to an average of "
407  << 1000.0 * dms::seconds_in_trig / double(trig_calls_here) << " ms per call";
408  qDebug() << Q_FUNC_INFO << "Redundancy of trig calls in this draw: "
409  << double(trig_redundancy_here) / double(trig_calls_here) * 100. << "%";
410  qDebug() << Q_FUNC_INFO << "CachedDms constructor calls so far: " << CachingDms::cachingdms_constructor_calls;
411  qDebug() << Q_FUNC_INFO << "Caching has prevented " << CachingDms::cachingdms_delta << " redundant trig function calls";
412  qDebug() << Q_FUNC_INFO << "Bad cache uses in this draw: " << cachingdms_bad_uses;
413 #endif
414 #ifdef PROFILE_UPDATECOORDS
415  qDebug() << Q_FUNC_INFO << "Spent " << StarObject::updateCoordsCpuTime << " seconds updating " << StarObject::starsUpdated
416  << " stars' coordinates (StarObject::updateCoords) for an average of "
417  << double(StarObject::updateCoordsCpuTime) / double(StarObject::starsUpdated) * 1.e6 << " us per star.";
418 #endif
419 
420 #else
421  Q_UNUSED(skyp)
422 #endif
423 }
424 
425 bool DeepStarComponent::openDataFile()
426 {
427  if (starReader.getFileHandle())
428  return true;
429 
430  starReader.openFile(dataFileName);
431  fileOpened = false;
432  if (!starReader.getFileHandle())
433  qCWarning(KSTARS) << "Failed to open deep star catalog " << dataFileName << ". Disabling it.";
434  else if (!starReader.readHeader())
435  qCWarning(KSTARS) << "Header read error for deep star catalog " << dataFileName << "!! Disabling it!";
436  else
437  {
438  qint16 faintmag;
439  quint8 htm_level;
440  int ret = 0;
441 
442  ret = fread(&faintmag, 2, 1, starReader.getFileHandle());
443  if (starReader.getByteSwap())
444  faintmag = bswap_16(faintmag);
445  if (starReader.guessRecordSize() == 16)
446  m_FaintMagnitude = faintmag / 1000.0;
447  else
448  m_FaintMagnitude = faintmag / 100.0;
449  ret = fread(&htm_level, 1, 1, starReader.getFileHandle());
450  qCInfo(KSTARS) << "Processing " << dataFileName << ", HTMesh Level" << htm_level;
451  m_skyMesh = SkyMesh::Instance(htm_level);
452  if (!m_skyMesh)
453  {
454  if (!(m_skyMesh = SkyMesh::Create(htm_level)))
455  {
456  qCWarning(KSTARS) << "Could not create HTMesh of level " << htm_level << " for catalog " << dataFileName
457  << ". Skipping it.";
458  return false;
459  }
460  }
461  ret = fread(&MSpT, 2, 1, starReader.getFileHandle());
462  if (starReader.getByteSwap())
463  MSpT = bswap_16(MSpT);
464  fileOpened = true;
465  qCInfo(KSTARS) << " Sky Mesh Size: " << m_skyMesh->size();
466  for (long int i = 0; i < m_skyMesh->size(); i++)
467  {
468  std::shared_ptr<StarBlockList> sbl(new StarBlockList(i, this));
469 
470  if (!sbl.get())
471  {
472  qCWarning(KSTARS) << "nullptr starBlockList. Expect trouble!";
473  }
474  m_starBlockList.append(sbl);
475  }
476  m_zoomMagLimit = 0.06;
477  }
478 
479  return fileOpened;
480 }
481 
483 {
484  // Currently, we only handle HD catalog indexes
485  return m_CatalogNumber.value(HDnum, nullptr); // TODO: Maybe, make this more general.
486 }
487 
488 // This uses the main star index for looking up nearby stars but then
489 // filters out objects with the generic name "star". We could easily
490 // build an index for just the named stars which would make this go
491 // much faster still. -jbb
492 //
493 
495 {
496  StarObject *oBest = nullptr;
497 
498 #ifdef KSTARS_LITE
499  m_zoomMagLimit = StarComponent::zoomMagnitudeLimit();
500 #endif
501  if (!fileOpened)
502  return nullptr;
503 
504  m_skyMesh->index(p, maxrad + 1.0, OBJ_NEAREST_BUF);
505 
506  MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF);
507 
508  while (region.hasNext())
509  {
510  Trixel currentRegion = region.next();
511 
512  // Safety check if the current region is in star block list
513  if ((int)currentRegion >= m_starBlockList.size())
514  continue;
515 
516  for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i)
517  {
518  std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i);
519  for (int j = 0; j < block->getStarCount(); ++j)
520  {
521 #ifdef KSTARS_LITE
522  StarObject *star = &(block->star(j)->star);
523 #else
524  StarObject *star = block->star(j);
525 #endif
526  if (!star)
527  continue;
528  if (star->mag() > m_zoomMagLimit)
529  continue;
530 
531  double r = star->angularDistanceTo(p).Degrees();
532  if (r < maxrad)
533  {
534  oBest = star;
535  maxrad = r;
536  }
537  }
538  }
539  }
540 
541  // TODO: What if we are looking around a point that's not on
542  // screen? objectNearest() will need to keep on filling up all
543  // trixels around the SkyPoint to find the best match in case it
544  // has not been found. Ideally, this should be implemented in a
545  // different method and should be called after all other
546  // candidates (eg: DeepSkyObject::objectNearest()) have been
547  // called.
548 
549  return oBest;
550 }
551 
552 bool DeepStarComponent::starsInAperture(QList<StarObject *> &list, const SkyPoint &center, float radius, float maglim)
553 {
554  if (maglim < triggerMag)
555  return false;
556 
557  // For DeepStarComponents, whether we use ra0() and dec0(), or
558  // ra() and dec(), should not matter, because the stars are
559  // repeated in all trixels that they will pass through, although
560  // the factuality of this statement needs to be verified
561 
562  // Ensure that we have deprecessed the (RA, Dec) to (RA0, Dec0)
563  Q_ASSERT(center.ra0().Degrees() >= 0.0);
564  Q_ASSERT(center.dec0().Degrees() <= 90.0);
565 
566  m_skyMesh->intersect(center.ra0().Degrees(), center.dec0().Degrees(), radius, (BufNum)OBJ_NEAREST_BUF);
567 
568  MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF);
569 
570  if (maglim < -28)
571  maglim = m_FaintMagnitude;
572 
573  while (region.hasNext())
574  {
575  Trixel currentRegion = region.next();
576  // FIXME: Build a better way to iterate over all stars.
577  // Ideally, StarBlockList should have such a facility.
578  std::shared_ptr<StarBlockList> sbl = m_starBlockList[currentRegion];
579  sbl->fillToMag(maglim);
580  for (int i = 0; i < sbl->getBlockCount(); ++i)
581  {
582  std::shared_ptr<StarBlock> block = sbl->block(i);
583  for (int j = 0; j < block->getStarCount(); ++j)
584  {
585 #ifdef KSTARS_LITE
586  StarObject *star = &(block->star(j)->star);
587 #else
588  StarObject *star = block->star(j);
589 #endif
590  if (star->mag() > maglim)
591  break; // Stars are organized by magnitude, so this should work
592  if (star->angularDistanceTo(&center).Degrees() <= radius)
593  list.append(star);
594  }
595  }
596  }
597 
598  return true;
599 }
600 
601 void DeepStarComponent::byteSwap(DeepStarData *stardata)
602 {
603  stardata->RA = bswap_32(stardata->RA);
604  stardata->Dec = bswap_32(stardata->Dec);
605  stardata->dRA = bswap_16(stardata->dRA);
606  stardata->dDec = bswap_16(stardata->dDec);
607  stardata->B = bswap_16(stardata->B);
608  stardata->V = bswap_16(stardata->V);
609 }
610 
611 void DeepStarComponent::byteSwap(StarData *stardata)
612 {
613  stardata->RA = bswap_32(stardata->RA);
614  stardata->Dec = bswap_32(stardata->Dec);
615  stardata->dRA = bswap_32(stardata->dRA);
616  stardata->dDec = bswap_32(stardata->dDec);
617  stardata->parallax = bswap_32(stardata->parallax);
618  stardata->HD = bswap_32(stardata->HD);
619  stardata->mag = bswap_16(stardata->mag);
620  stardata->bv_index = bswap_16(stardata->bv_index);
621 }
622 
623 bool DeepStarComponent::verifySBLIntegrity()
624 {
625  float faintMag = -5.0;
626  bool integrity = true;
627 
628  for (Trixel trixel = 0; trixel < m_skyMesh->size(); ++trixel)
629  {
630  for (int i = 0; i < m_starBlockList[trixel]->getBlockCount(); ++i)
631  {
632  std::shared_ptr<StarBlock> block = m_starBlockList[trixel]->block(i);
633 
634  if (i == 0)
635  faintMag = block->getBrightMag();
636  // NOTE: Assumes 2 decimal places in magnitude field. TODO: Change if it ever does change
637  if (block->getBrightMag() != faintMag && (block->getBrightMag() - faintMag) > 0.5)
638  {
639  qCWarning(KSTARS) << "Trixel " << trixel << ": ERROR: faintMag of prev block = " << faintMag
640  << ", brightMag of block #" << i << " = " << block->getBrightMag();
641  integrity = false;
642  }
643  if (i > 1 && (!block->prev))
644  qCWarning(KSTARS) << "Trixel " << trixel << ": ERROR: Block" << i << "is unlinked in LRU Cache";
645  if (block->prev && block->prev->parent == m_starBlockList[trixel].get() &&
646  block->prev != m_starBlockList[trixel]->block(i - 1))
647  {
648  qCWarning(KSTARS) << "Trixel " << trixel
649  << ": ERROR: SBF LRU Cache linked list seems to be broken at before block " << i;
650  integrity = false;
651  }
652  faintMag = block->getFaintMag();
653  }
654  }
655  return integrity;
656 }
void append(const T &value)
bool selected() override
int guessRecordSize() const
Return a guessed record size.
const T value(const Key &key) const const
FILE * getFileHandle() const
Get the file handle corresponding to the currently open file.
bool 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...
A 32-byte Structure that holds star data.
Definition: stardata.h:17
bool markFirst(std::shared_ptr< StarBlock > &block)
Mark a StarBlock as most recently used and sync its drawID with the current drawID.
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
bool readHeader()
Read the header and index table from the file and fill up the QVector s with the entries.
void aperture(SkyPoint *center, double radius, MeshBufNum_t bufNum=DRAW_BUF)
finds the set of trixels that cover the circular aperture specified after first performing a reverse ...
Definition: skymesh.cpp:56
void append(const T &value)
bool getByteSwap() const
Should we do byte swapping?
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
float mag() const
Definition: skyobject.h:206
StarObject * findByHDIndex(int HDnum)
qint32 RA
Raw signed 32-bit RA value.
Definition: stardata.h:19
QHash::iterator insert(const Key &key, const T &value)
void closeFile()
Close the binary data file.
unsigned int getRecordCount(int id) const
Returns the number of records under the given index ID.
Store several time-dependent astronomical quantities.
Definition: ksnumbers.h:42
qint64 restart()
subclass of SkyObject specialized for stars.
Definition: starobject.h:32
QString getError()
Get error string.
const T & at(int i) const const
virtual bool drawPointSource(const SkyPoint *loc, float mag, char sp='A')=0
Draw a point source (e.g., a star).
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
Draws things on the sky, without regard to backend.
Definition: skypainter.h:37
void update(KSNumbers *num) override
Update the sky position(s) of this component.
qint64 elapsed() const const
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
Definition: skypoint.cpp:899
bool hasNext() const
true if there are more trixel to iterate over.
Definition: MeshIterator.h:27
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition: skymesh.cpp:39
char spchar() const
Returns just the first character of the spectral type string.
Definition: starobject.cpp:554
bool markNext(std::shared_ptr< StarBlock > &after, std::shared_ptr< StarBlock > &block)
Rank a given StarBlock after another given StarBlock in the LRU list and sync its drawID with the cur...
qint32 HD
unsigned 32-bit Henry Draper Index.
Definition: stardata.h:24
void reset() const
sets the count back to zero so you can use this iterator to iterate again over the same result set.
Definition: MeshIterator.h:40
const double & Degrees() const
Definition: dms.h:141
qint16 mag
signed 16-bit raw magnitude.
Definition: stardata.h:25
Canvas widget for displaying the sky bitmap; also handles user interaction events.
Definition: skymap.h:52
A 16-byte structure that holds star data for really faint stars.
void draw(SkyPainter *skyp) override
Draw the object on the SkyMap skyp a pointer to the SkyPainter to use.
void JITupdate()
added for JIT updates from both StarComponent and ConstellationLines
Definition: starobject.cpp:526
qint32 Dec
Raw signed 32-bit DE value.
Definition: stardata.h:20
int size() const const
A factory that creates StarBlocks and recycles them in an LRU Cache.
Trixel index(const SkyPoint *p)
returns the index of the trixel containing p.
Definition: skymesh.cpp:86
void blockingMap(Sequence &sequence, MapFunctor function)
Information about an object in the sky.
Definition: skyobject.h:41
SkyObject * objectNearest(SkyPoint *p, double &maxrad) override
static SkyMesh * Create(int level)
creates the single instance of SkyMesh.
Definition: skymesh.cpp:25
FILE * openFile(const QString &fileName)
WARNING: This function may not be compatible in other locales, because it calls QString::toAscii.
Trixel next() const
returns the next trixel
Definition: MeshIterator.h:31
long getDataOffset() const
Returns the offset at which the data begins.
int getErrorNumber()
Get error number.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:53 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.