File indexing completed on 2025-01-19 09:45:58
0001 /* 0002 SPDX-FileCopyrightText: 2008 Akarsh Simha Thomas Kabelmann <akarshsimha@gmail.com, thomas.kabelmann@gmx.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "deepstarcomponent.h" 0008 0009 #include "byteorder.h" 0010 #include "kstarsdata.h" 0011 #include "Options.h" 0012 #ifndef KSTARS_LITE 0013 #include "skymap.h" 0014 #endif 0015 #include "skymesh.h" 0016 #include "skypainter.h" 0017 #include "starblock.h" 0018 #include "starcomponent.h" 0019 #include "htmesh/MeshIterator.h" 0020 #include "projections/projector.h" 0021 0022 #include <qplatformdefs.h> 0023 #include <QtConcurrent> 0024 #include <QElapsedTimer> 0025 0026 #include <kstars_debug.h> 0027 0028 #ifdef _WIN32 0029 #include <windows.h> 0030 #endif 0031 0032 DeepStarComponent::DeepStarComponent(SkyComposite *parent, QString fileName, float trigMag, bool staticstars) 0033 : ListComponent(parent), m_reindexNum(J2000), triggerMag(trigMag), m_FaintMagnitude(-5.0), staticStars(staticstars), 0034 dataFileName(fileName) 0035 { 0036 fileOpened = false; 0037 openDataFile(); 0038 if (staticStars) 0039 loadStaticStars(); 0040 qCInfo(KSTARS) << "Loaded DSO catalog file: " << dataFileName; 0041 } 0042 0043 DeepStarComponent::~DeepStarComponent() 0044 { 0045 if (fileOpened) 0046 starReader.closeFile(); 0047 fileOpened = false; 0048 } 0049 0050 bool DeepStarComponent::loadStaticStars() 0051 { 0052 FILE *dataFile; 0053 0054 if (!staticStars) 0055 return true; 0056 if (!fileOpened) 0057 return false; 0058 0059 dataFile = starReader.getFileHandle(); 0060 rewind(dataFile); 0061 0062 if (!starReader.readHeader()) 0063 { 0064 qCCritical(KSTARS) << "Error reading header of catalog file " << dataFileName << ": " << starReader.getErrorNumber() 0065 << ": " << starReader.getError(); 0066 return false; 0067 } 0068 0069 quint8 recordSize = starReader.guessRecordSize(); 0070 0071 if (recordSize != 16 && recordSize != 32) 0072 { 0073 qCCritical(KSTARS) << "Cannot understand catalog file " << dataFileName; 0074 return false; 0075 } 0076 0077 //KDE_fseek(dataFile, starReader.getDataOffset(), SEEK_SET); 0078 QT_FSEEK(dataFile, starReader.getDataOffset(), SEEK_SET); 0079 0080 qint16 faintmag; 0081 quint8 htm_level; 0082 quint16 t_MSpT; 0083 int ret = 0; 0084 0085 ret = fread(&faintmag, 2, 1, dataFile); 0086 if (starReader.getByteSwap()) 0087 faintmag = bswap_16(faintmag); 0088 ret = fread(&htm_level, 1, 1, dataFile); 0089 ret = fread(&t_MSpT, 2, 1, dataFile); // Unused 0090 if (starReader.getByteSwap()) 0091 faintmag = bswap_16(faintmag); 0092 0093 // TODO: Read the multiplying factor from the dataFile 0094 m_FaintMagnitude = faintmag / 100.0; 0095 0096 if (htm_level != m_skyMesh->level()) 0097 qCWarning(KSTARS) << "HTM Level in shallow star data file and HTM Level in m_skyMesh do not match. EXPECT TROUBLE!"; 0098 0099 // JM 2012-12-05: Breaking into 2 loops instead of one previously with multiple IF checks for recordSize 0100 // While the CPU branch prediction might not suffer any penalties since the branch prediction after a few times 0101 // should always gets it right. It's better to do it this way to avoid any chances since the compiler might not optimize it. 0102 if (recordSize == 32) 0103 { 0104 for (Trixel i = 0; i < m_skyMesh->size(); ++i) 0105 { 0106 Trixel trixel = i; 0107 quint64 records = starReader.getRecordCount(i); 0108 std::shared_ptr<StarBlock> SB(new StarBlock(records)); 0109 0110 if (!SB.get()) 0111 qCCritical(KSTARS) << "ERROR: Could not allocate new StarBlock to hold shallow unnamed stars for trixel " 0112 << trixel; 0113 0114 m_starBlockList.at(trixel)->setStaticBlock(SB); 0115 0116 for (quint64 j = 0; j < records; ++j) 0117 { 0118 bool fread_success = fread(&stardata, sizeof(StarData), 1, dataFile); 0119 0120 if (!fread_success) 0121 { 0122 qCCritical(KSTARS) << "ERROR: Could not read StarData structure for star #" << j << " under trixel #" 0123 << trixel; 0124 } 0125 0126 /* Swap Bytes when required */ 0127 if (starReader.getByteSwap()) 0128 byteSwap(&stardata); 0129 0130 /* Initialize star with data just read. */ 0131 StarObject *star; 0132 #ifdef KSTARS_LITE 0133 star = &(SB->addStar(stardata)->star); 0134 #else 0135 star = SB->addStar(stardata); 0136 #endif 0137 if (star) 0138 { 0139 //KStarsData* data = KStarsData::Instance(); 0140 //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); 0141 //if( star->getHDIndex() != 0 ) 0142 if (stardata.HD) 0143 m_CatalogNumber.insert(stardata.HD, star); 0144 } 0145 else 0146 { 0147 qCCritical(KSTARS) << "CODE ERROR: More unnamed static stars in trixel " << trixel 0148 << " than we allocated space for!"; 0149 } 0150 } 0151 } 0152 } 0153 else 0154 { 0155 for (Trixel i = 0; i < m_skyMesh->size(); ++i) 0156 { 0157 Trixel trixel = i; 0158 quint64 records = starReader.getRecordCount(i); 0159 std::shared_ptr<StarBlock> SB(new StarBlock(records)); 0160 0161 if (!SB.get()) 0162 qCCritical(KSTARS) << "Could not allocate new StarBlock to hold shallow unnamed stars for trixel " 0163 << trixel; 0164 0165 m_starBlockList.at(trixel)->setStaticBlock(SB); 0166 0167 for (quint64 j = 0; j < records; ++j) 0168 { 0169 bool fread_success = false; 0170 fread_success = fread(&deepstardata, sizeof(DeepStarData), 1, dataFile); 0171 0172 if (!fread_success) 0173 { 0174 qCCritical(KSTARS) << "Could not read StarData structure for star #" << j << " under trixel #" 0175 << trixel; 0176 } 0177 0178 /* Swap Bytes when required */ 0179 if (starReader.getByteSwap()) 0180 byteSwap(&deepstardata); 0181 0182 /* Initialize star with data just read. */ 0183 StarObject *star; 0184 #ifdef KSTARS_LITE 0185 star = &(SB->addStar(stardata)->star); 0186 #else 0187 star = SB->addStar(deepstardata); 0188 #endif 0189 if (star) 0190 { 0191 //KStarsData* data = KStarsData::Instance(); 0192 //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); 0193 //if( star->getHDIndex() != 0 ) 0194 if (stardata.HD) 0195 m_CatalogNumber.insert(stardata.HD, star); 0196 } 0197 else 0198 { 0199 qCCritical(KSTARS) << "CODE ERROR: More unnamed static stars in trixel " << trixel 0200 << " than we allocated space for!"; 0201 } 0202 } 0203 } 0204 } 0205 0206 return true; 0207 } 0208 0209 bool DeepStarComponent::selected() 0210 { 0211 return Options::showStars() && fileOpened; 0212 } 0213 0214 bool openIndexFile() 0215 { 0216 // TODO: Work out the details 0217 /* 0218 if( hdidxReader.openFile( "Henry-Draper.idx" ) ) 0219 qDebug() << Q_FUNC_INFO << "Could not open HD Index file. Search by HD numbers for deep stars will not work."; 0220 */ 0221 return 0; 0222 } 0223 0224 //This function is empty for a reason; we override the normal 0225 //update function in favor of JiT updates for stars. 0226 void DeepStarComponent::update(KSNumbers *) 0227 { 0228 } 0229 0230 // TODO: Optimize draw, if it is worth it. 0231 void DeepStarComponent::draw(SkyPainter *skyp) 0232 { 0233 #ifndef KSTARS_LITE 0234 if (!fileOpened) 0235 return; 0236 0237 #ifdef PROFILE_SINCOS 0238 long trig_calls_here = -dms::trig_function_calls; 0239 long trig_redundancy_here = -dms::redundant_trig_function_calls; 0240 long cachingdms_bad_uses = -CachingDms::cachingdms_bad_uses; 0241 dms::seconds_in_trig = 0.; 0242 #endif 0243 0244 #ifdef PROFILE_UPDATECOORDS 0245 StarObject::updateCoordsCpuTime = 0.; 0246 StarObject::starsUpdated = 0; 0247 #endif 0248 SkyMap *map = SkyMap::Instance(); 0249 KStarsData *data = KStarsData::Instance(); 0250 UpdateID updateID = data->updateID(); 0251 0252 //FIXME_FOV -- maybe not clamp like that... 0253 float radius = map->projector()->fov(); 0254 if (radius > 90.0) 0255 radius = 90.0; 0256 0257 if (m_skyMesh != SkyMesh::Instance() && m_skyMesh->inDraw()) 0258 { 0259 printf("Warning: aborting concurrent DeepStarComponent::draw()"); 0260 } 0261 bool checkSlewing = (map->isSlewing() && Options::hideOnSlew()); 0262 0263 //shortcuts to inform whether to draw different objects 0264 bool hideFaintStars(checkSlewing && Options::hideStars()); 0265 double hideStarsMag = Options::magLimitHideStar(); 0266 0267 //adjust maglimit for ZoomLevel 0268 // double lgmin = log10(MINZOOM); 0269 // double lgmax = log10(MAXZOOM); 0270 // double lgz = log10(Options::zoomFactor()); 0271 // TODO: Enable hiding of faint stars 0272 0273 float maglim = StarComponent::zoomMagnitudeLimit(); 0274 0275 if (maglim < triggerMag) 0276 return; 0277 0278 m_zoomMagLimit = maglim; 0279 0280 m_skyMesh->inDraw(true); 0281 0282 SkyPoint *focus = map->focus(); 0283 m_skyMesh->aperture(focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing 0284 0285 MeshIterator region(m_skyMesh, DRAW_BUF); 0286 0287 // If we are to hide the fainter stars (eg: while slewing), we set the magnitude limit to hideStarsMag. 0288 if (hideFaintStars && maglim > hideStarsMag) 0289 maglim = hideStarsMag; 0290 0291 StarBlockFactory *m_StarBlockFactory = StarBlockFactory::Instance(); 0292 // m_StarBlockFactory->drawID = m_skyMesh->drawID(); 0293 // qDebug() << Q_FUNC_INFO << "Mesh size = " << m_skyMesh->size() << "; drawID = " << m_skyMesh->drawID(); 0294 QElapsedTimer t; 0295 int nTrixels = 0; 0296 0297 t_dynamicLoad = 0; 0298 t_updateCache = 0; 0299 t_drawUnnamed = 0; 0300 0301 visibleStarCount = 0; 0302 0303 t.start(); 0304 0305 // Mark used blocks in the LRU Cache. Not required for static stars 0306 if (!staticStars) 0307 { 0308 while (region.hasNext()) 0309 { 0310 Trixel currentRegion = region.next(); 0311 for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i) 0312 { 0313 std::shared_ptr<StarBlock> prevBlock = ((i >= 1) ? m_starBlockList.at(currentRegion)->block( 0314 i - 1) : std::shared_ptr<StarBlock>()); 0315 std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i); 0316 0317 if (i == 0 && !m_StarBlockFactory->markFirst(block)) 0318 qCWarning(KSTARS) << "markFirst failed in trixel" << currentRegion; 0319 if (i > 0 && !m_StarBlockFactory->markNext(prevBlock, block)) 0320 qCWarning(KSTARS) << "markNext failed in trixel" << currentRegion << "while marking block" << i; 0321 if (i < m_starBlockList.at(currentRegion)->getBlockCount() && 0322 m_starBlockList.at(currentRegion)->block(i)->getFaintMag() < maglim) 0323 break; 0324 } 0325 } 0326 t_updateCache = t.elapsed(); 0327 region.reset(); 0328 } 0329 0330 while (region.hasNext()) 0331 { 0332 ++nTrixels; 0333 Trixel currentRegion = region.next(); 0334 0335 // NOTE: We are guessing that the last 1.5/16 magnitudes in the catalog are just additions and the star catalog 0336 // is actually supposed to reach out continuously enough only to mag m_FaintMagnitude * ( 1 - 1.5/16 ) 0337 // TODO: Is there a better way? We may have to change the magnitude tolerance if the catalog changes 0338 // Static stars need not execute fillToMag 0339 0340 // Safety check if the current region is in star block list 0341 if (currentRegion >= m_starBlockList.size()) 0342 continue; 0343 0344 if (!staticStars) 0345 { 0346 m_starBlockList.at(currentRegion)->fillToMag(maglim); 0347 } 0348 0349 // if (!staticStars && !m_starBlockList.at(currentRegion)->fillToMag(maglim) && 0350 // maglim <= m_FaintMagnitude * (1 - 1.5 / 16)) 0351 // { 0352 // qCWarning(KSTARS) << "SBL::fillToMag( " << maglim << " ) failed for trixel " << currentRegion; 0353 // } 0354 0355 t_dynamicLoad += t.restart(); 0356 0357 // qDebug() << Q_FUNC_INFO << "Drawing SBL for trixel " << currentRegion << ", SBL has " 0358 // << m_starBlockList[ currentRegion ]->getBlockCount() << " blocks"; 0359 0360 // REMARK: The following should never carry state, except for const parameters like updateID and maglim 0361 std::function<void(std::shared_ptr<StarBlock>)> mapFunction = [&updateID, &maglim](std::shared_ptr<StarBlock> myBlock) 0362 { 0363 for (StarObject &star : myBlock->contents()) 0364 { 0365 if (star.updateID != updateID) 0366 star.JITupdate(); 0367 if (star.mag() > maglim) 0368 break; 0369 } 0370 }; 0371 0372 QtConcurrent::blockingMap(m_starBlockList.at(currentRegion)->contents(), mapFunction); 0373 0374 for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i) 0375 { 0376 std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i); 0377 // qDebug() << Q_FUNC_INFO << "---> Drawing stars from block " << i << " of trixel " << 0378 // currentRegion << ". SB has " << block->getStarCount() << " stars"; 0379 for (int j = 0; j < block->getStarCount(); j++) 0380 { 0381 StarObject *curStar = block->star(j); 0382 0383 // qDebug() << Q_FUNC_INFO << "We claim that he's from trixel " << currentRegion 0384 //<< ", and indexStar says he's from " << m_skyMesh->indexStar( curStar ); 0385 0386 float mag = curStar->mag(); 0387 0388 if (mag > maglim) 0389 break; 0390 0391 if (skyp->drawPointSource(curStar, mag, curStar->spchar())) 0392 visibleStarCount++; 0393 } 0394 } 0395 0396 // DEBUG: Uncomment to identify problems with Star Block Factory / preservation of Magnitude Order in the LRU Cache 0397 // verifySBLIntegrity(); 0398 t_drawUnnamed += t.restart(); 0399 } 0400 m_skyMesh->inDraw(false); 0401 #ifdef PROFILE_SINCOS 0402 trig_calls_here += dms::trig_function_calls; 0403 trig_redundancy_here += dms::redundant_trig_function_calls; 0404 cachingdms_bad_uses += CachingDms::cachingdms_bad_uses; 0405 qDebug() << Q_FUNC_INFO << "Spent " << dms::seconds_in_trig << " seconds doing " << trig_calls_here 0406 << " trigonometric function calls amounting to an average of " 0407 << 1000.0 * dms::seconds_in_trig / double(trig_calls_here) << " ms per call"; 0408 qDebug() << Q_FUNC_INFO << "Redundancy of trig calls in this draw: " 0409 << double(trig_redundancy_here) / double(trig_calls_here) * 100. << "%"; 0410 qDebug() << Q_FUNC_INFO << "CachedDms constructor calls so far: " << CachingDms::cachingdms_constructor_calls; 0411 qDebug() << Q_FUNC_INFO << "Caching has prevented " << CachingDms::cachingdms_delta << " redundant trig function calls"; 0412 qDebug() << Q_FUNC_INFO << "Bad cache uses in this draw: " << cachingdms_bad_uses; 0413 #endif 0414 #ifdef PROFILE_UPDATECOORDS 0415 qDebug() << Q_FUNC_INFO << "Spent " << StarObject::updateCoordsCpuTime << " seconds updating " << StarObject::starsUpdated 0416 << " stars' coordinates (StarObject::updateCoords) for an average of " 0417 << double(StarObject::updateCoordsCpuTime) / double(StarObject::starsUpdated) * 1.e6 << " us per star."; 0418 #endif 0419 0420 #else 0421 Q_UNUSED(skyp) 0422 #endif 0423 } 0424 0425 bool DeepStarComponent::openDataFile() 0426 { 0427 if (starReader.getFileHandle()) 0428 return true; 0429 0430 starReader.openFile(dataFileName); 0431 fileOpened = false; 0432 if (!starReader.getFileHandle()) 0433 qCWarning(KSTARS) << "Failed to open deep star catalog " << dataFileName << ". Disabling it."; 0434 else if (!starReader.readHeader()) 0435 qCWarning(KSTARS) << "Header read error for deep star catalog " << dataFileName << "!! Disabling it!"; 0436 else 0437 { 0438 qint16 faintmag; 0439 quint8 htm_level; 0440 int ret = 0; 0441 0442 ret = fread(&faintmag, 2, 1, starReader.getFileHandle()); 0443 if (starReader.getByteSwap()) 0444 faintmag = bswap_16(faintmag); 0445 if (starReader.guessRecordSize() == 16) 0446 m_FaintMagnitude = faintmag / 1000.0; 0447 else 0448 m_FaintMagnitude = faintmag / 100.0; 0449 ret = fread(&htm_level, 1, 1, starReader.getFileHandle()); 0450 qCInfo(KSTARS) << "Processing " << dataFileName << ", HTMesh Level" << htm_level; 0451 m_skyMesh = SkyMesh::Instance(htm_level); 0452 if (!m_skyMesh) 0453 { 0454 if (!(m_skyMesh = SkyMesh::Create(htm_level))) 0455 { 0456 qCWarning(KSTARS) << "Could not create HTMesh of level " << htm_level << " for catalog " << dataFileName 0457 << ". Skipping it."; 0458 return false; 0459 } 0460 } 0461 ret = fread(&MSpT, 2, 1, starReader.getFileHandle()); 0462 if (starReader.getByteSwap()) 0463 MSpT = bswap_16(MSpT); 0464 fileOpened = true; 0465 qCInfo(KSTARS) << " Sky Mesh Size: " << m_skyMesh->size(); 0466 for (long int i = 0; i < m_skyMesh->size(); i++) 0467 { 0468 std::shared_ptr<StarBlockList> sbl(new StarBlockList(i, this)); 0469 0470 if (!sbl.get()) 0471 { 0472 qCWarning(KSTARS) << "nullptr starBlockList. Expect trouble!"; 0473 } 0474 m_starBlockList.append(sbl); 0475 } 0476 m_zoomMagLimit = 0.06; 0477 } 0478 0479 return fileOpened; 0480 } 0481 0482 StarObject *DeepStarComponent::findByHDIndex(int HDnum) 0483 { 0484 // Currently, we only handle HD catalog indexes 0485 return m_CatalogNumber.value(HDnum, nullptr); // TODO: Maybe, make this more general. 0486 } 0487 0488 // This uses the main star index for looking up nearby stars but then 0489 // filters out objects with the generic name "star". We could easily 0490 // build an index for just the named stars which would make this go 0491 // much faster still. -jbb 0492 // 0493 0494 SkyObject *DeepStarComponent::objectNearest(SkyPoint *p, double &maxrad) 0495 { 0496 StarObject *oBest = nullptr; 0497 0498 #ifdef KSTARS_LITE 0499 m_zoomMagLimit = StarComponent::zoomMagnitudeLimit(); 0500 #endif 0501 if (!fileOpened) 0502 return nullptr; 0503 0504 m_skyMesh->index(p, maxrad + 1.0, OBJ_NEAREST_BUF); 0505 0506 MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF); 0507 0508 while (region.hasNext()) 0509 { 0510 Trixel currentRegion = region.next(); 0511 0512 // Safety check if the current region is in star block list 0513 if ((int)currentRegion >= m_starBlockList.size()) 0514 continue; 0515 0516 for (int i = 0; i < m_starBlockList.at(currentRegion)->getBlockCount(); ++i) 0517 { 0518 std::shared_ptr<StarBlock> block = m_starBlockList.at(currentRegion)->block(i); 0519 for (int j = 0; j < block->getStarCount(); ++j) 0520 { 0521 #ifdef KSTARS_LITE 0522 StarObject *star = &(block->star(j)->star); 0523 #else 0524 StarObject *star = block->star(j); 0525 #endif 0526 if (!star) 0527 continue; 0528 if (star->mag() > m_zoomMagLimit) 0529 continue; 0530 0531 double r = star->angularDistanceTo(p).Degrees(); 0532 if (r < maxrad) 0533 { 0534 oBest = star; 0535 maxrad = r; 0536 } 0537 } 0538 } 0539 } 0540 0541 // TODO: What if we are looking around a point that's not on 0542 // screen? objectNearest() will need to keep on filling up all 0543 // trixels around the SkyPoint to find the best match in case it 0544 // has not been found. Ideally, this should be implemented in a 0545 // different method and should be called after all other 0546 // candidates (eg: DeepSkyObject::objectNearest()) have been 0547 // called. 0548 0549 return oBest; 0550 } 0551 0552 bool DeepStarComponent::starsInAperture(QList<StarObject *> &list, const SkyPoint ¢er, float radius, float maglim) 0553 { 0554 if (maglim < triggerMag) 0555 return false; 0556 0557 // For DeepStarComponents, whether we use ra0() and dec0(), or 0558 // ra() and dec(), should not matter, because the stars are 0559 // repeated in all trixels that they will pass through, although 0560 // the factuality of this statement needs to be verified 0561 0562 // Ensure that we have deprecessed the (RA, Dec) to (RA0, Dec0) 0563 Q_ASSERT(center.ra0().Degrees() >= 0.0); 0564 Q_ASSERT(center.dec0().Degrees() <= 90.0); 0565 0566 m_skyMesh->intersect(center.ra0().Degrees(), center.dec0().Degrees(), radius, (BufNum)OBJ_NEAREST_BUF); 0567 0568 MeshIterator region(m_skyMesh, OBJ_NEAREST_BUF); 0569 0570 if (maglim < -28) 0571 maglim = m_FaintMagnitude; 0572 0573 while (region.hasNext()) 0574 { 0575 Trixel currentRegion = region.next(); 0576 // FIXME: Build a better way to iterate over all stars. 0577 // Ideally, StarBlockList should have such a facility. 0578 std::shared_ptr<StarBlockList> sbl = m_starBlockList[currentRegion]; 0579 sbl->fillToMag(maglim); 0580 for (int i = 0; i < sbl->getBlockCount(); ++i) 0581 { 0582 std::shared_ptr<StarBlock> block = sbl->block(i); 0583 for (int j = 0; j < block->getStarCount(); ++j) 0584 { 0585 #ifdef KSTARS_LITE 0586 StarObject *star = &(block->star(j)->star); 0587 #else 0588 StarObject *star = block->star(j); 0589 #endif 0590 if (star->mag() > maglim) 0591 break; // Stars are organized by magnitude, so this should work 0592 if (star->angularDistanceTo(¢er).Degrees() <= radius) 0593 list.append(star); 0594 } 0595 } 0596 } 0597 0598 return true; 0599 } 0600 0601 void DeepStarComponent::byteSwap(DeepStarData *stardata) 0602 { 0603 stardata->RA = bswap_32(stardata->RA); 0604 stardata->Dec = bswap_32(stardata->Dec); 0605 stardata->dRA = bswap_16(stardata->dRA); 0606 stardata->dDec = bswap_16(stardata->dDec); 0607 stardata->B = bswap_16(stardata->B); 0608 stardata->V = bswap_16(stardata->V); 0609 } 0610 0611 void DeepStarComponent::byteSwap(StarData *stardata) 0612 { 0613 stardata->RA = bswap_32(stardata->RA); 0614 stardata->Dec = bswap_32(stardata->Dec); 0615 stardata->dRA = bswap_32(stardata->dRA); 0616 stardata->dDec = bswap_32(stardata->dDec); 0617 stardata->parallax = bswap_32(stardata->parallax); 0618 stardata->HD = bswap_32(stardata->HD); 0619 stardata->mag = bswap_16(stardata->mag); 0620 stardata->bv_index = bswap_16(stardata->bv_index); 0621 } 0622 0623 bool DeepStarComponent::verifySBLIntegrity() 0624 { 0625 float faintMag = -5.0; 0626 bool integrity = true; 0627 0628 for (Trixel trixel = 0; trixel < m_skyMesh->size(); ++trixel) 0629 { 0630 for (int i = 0; i < m_starBlockList[trixel]->getBlockCount(); ++i) 0631 { 0632 std::shared_ptr<StarBlock> block = m_starBlockList[trixel]->block(i); 0633 0634 if (i == 0) 0635 faintMag = block->getBrightMag(); 0636 // NOTE: Assumes 2 decimal places in magnitude field. TODO: Change if it ever does change 0637 if (block->getBrightMag() != faintMag && (block->getBrightMag() - faintMag) > 0.5) 0638 { 0639 qCWarning(KSTARS) << "Trixel " << trixel << ": ERROR: faintMag of prev block = " << faintMag 0640 << ", brightMag of block #" << i << " = " << block->getBrightMag(); 0641 integrity = false; 0642 } 0643 if (i > 1 && (!block->prev)) 0644 qCWarning(KSTARS) << "Trixel " << trixel << ": ERROR: Block" << i << "is unlinked in LRU Cache"; 0645 if (block->prev && block->prev->parent == m_starBlockList[trixel].get() && 0646 block->prev != m_starBlockList[trixel]->block(i - 1)) 0647 { 0648 qCWarning(KSTARS) << "Trixel " << trixel 0649 << ": ERROR: SBF LRU Cache linked list seems to be broken at before block " << i; 0650 integrity = false; 0651 } 0652 faintMag = block->getFaintMag(); 0653 } 0654 } 0655 return integrity; 0656 }