//Reimplement draw function so that we have control over the order of //elements, and we can add object labels // //The order in which components are drawn naturally determines the //z-ordering (the layering) of the components. Objects which //should appear "behind" others should be drawn first. void SkyMapComposite::draw( SkyPainter *skyp ) { SkyMap *map = SkyMap::Instance(); KStarsData *data = KStarsData::Instance(); // We delay one draw cycle before re-indexing // we MUST ensure CLines do not get re-indexed while we use DRAW_BUF // so we do it here. m_CLines->reindex( &m_reindexNum ); // This queues re-indexing for the next draw cycle m_reindexNum = KSNumbers( data->updateNum()->julianDay() ); // This ensures that the JIT updates are synchronized for the entire draw // cycle so the sky moves as a single sheet. May not be needed. data->syncUpdateIDs(); // prepare the aperture // FIXME_FOV: We may want to rejigger this to allow // wide-angle views --hdevalence float radius = map->projector()->fov(); if ( radius > 180.0 ) radius = 180.0; if ( m_skyMesh->inDraw() ) { printf("Warning: aborting concurrent SkyMapComposite::draw()\n"); return; } m_skyMesh->inDraw( true ); SkyPoint* focus = map->focus(); m_skyMesh->aperture( focus, radius + 1.0, DRAW_BUF ); // divide by 2 for testing // create the no-precess aperture if needed if ( Options::showEquatorialGrid() || Options::showHorizontalGrid() || Options::showCBounds() || Options::showEquator() ) { m_skyMesh->index( focus, radius + 1.0, NO_PRECESS_BUF ); } // clear marks from old labels and prep fonts m_skyLabeler->reset( map ); m_skyLabeler->useStdFont(); // info boxes have highest label priority // FIXME: REGRESSION. Labeler now know nothing about infoboxes // map->infoBoxes()->reserveBoxes( psky ); if( KStars::Instance() ) { const QList<SkyObject*> obsList = KStarsData::Instance()->observingList()->sessionList(); if( Options::obsListText() ) foreach( SkyObject* obj, obsList ) { SkyLabeler::AddLabel( obj, SkyLabeler::RUDE_LABEL ); } }
void StarComponent::draw( SkyPainter *skyp ) { if( !selected() ) return; SkyMap *map = SkyMap::Instance(); const Projector *proj = map->projector(); KStarsData* data = KStarsData::Instance(); UpdateID updateID = data->updateID(); bool checkSlewing = ( map->isSlewing() && Options::hideOnSlew() ); m_hideLabels = checkSlewing || !( Options::showStarMagnitudes() || Options::showStarNames() ); //shortcuts to inform whether to draw different objects bool hideFaintStars = checkSlewing && Options::hideStars(); double hideStarsMag = Options::magLimitHideStar(); reindex( data->updateNum() ); double lgmin = log10(MINZOOM); double lgmax = log10(MAXZOOM); double lgz = log10(Options::zoomFactor()); double maglim; m_zoomMagLimit = maglim = zoomMagnitudeLimit(); double labelMagLim = Options::starLabelDensity() / 5.0; labelMagLim += ( 12.0 - labelMagLim ) * ( lgz - lgmin) / (lgmax - lgmin ); if( labelMagLim > 8.0 ) labelMagLim = 8.0; //Calculate sizeMagLim // Old formula: // float sizeMagLim = ( 2.000 + 2.444 * Options::memUsage() / 10.0 ) * ( lgz - lgmin ) + 5.8; // Using the maglim to compute the sizes of stars reduces // discernability between brighter and fainter stars at high zoom // levels. To fix that, we use an "arbitrary" constant in place of // the variable star density. // Not using this formula now. // float sizeMagLim = 4.444 * ( lgz - lgmin ) + 5.0; float sizeMagLim = zoomMagnitudeLimit(); if( sizeMagLim > faintMagnitude() * ( 1 - 1.5/16 ) ) sizeMagLim = faintMagnitude() * ( 1 - 1.5/16 ); skyp->setSizeMagLimit(sizeMagLim); //Loop for drawing star images MeshIterator region(m_skyMesh, DRAW_BUF); magLim = maglim; // If we are hiding faint stars, then maglim is really the brighter of hideStarsMag and maglim if( hideFaintStars && maglim > hideStarsMag ) maglim = hideStarsMag; m_StarBlockFactory->drawID = m_skyMesh->drawID(); int nTrixels = 0; while( region.hasNext() ) { ++nTrixels; Trixel currentRegion = region.next(); StarList* starList = m_starIndex->at( currentRegion ); for (int i=0; i < starList->size(); ++i) { StarObject *curStar = starList->at( i ); if( !curStar ) continue; float mag = curStar->mag(); // break loop if maglim is reached if ( mag > maglim ) break; if ( curStar->updateID != updateID ) curStar->JITupdate(); bool drawn = skyp->drawPointSource( curStar, mag, curStar->spchar() ); //FIXME_SKYPAINTER: find a better way to do this. if ( drawn && !(m_hideLabels || mag > labelMagLim) ) addLabel( proj->toScreen(curStar), curStar ); } } // Draw focusStar if not null if( focusStar ) { if ( focusStar->updateID != updateID ) focusStar->JITupdate(); float mag = focusStar->mag(); skyp->drawPointSource(focusStar, mag, focusStar->spchar() ); } // Now draw each of our DeepStarComponents for( int i =0; i < m_DeepStarComponents.size(); ++i ) { m_DeepStarComponents.at( i )->draw( skyp ); } }
// TODO: Optimize draw, if it is worth it. void DeepStarComponent::draw( SkyPainter *skyp ) { #ifndef KSTARS_LITE if ( !fileOpened ) return; #ifdef PROFILE_SINCOS long trig_calls_here = - dms::trig_function_calls; long trig_redundancy_here = - dms::redundant_trig_function_calls; long cachingdms_bad_uses = -CachingDms::cachingdms_bad_uses; dms::seconds_in_trig = 0.; #endif #ifdef PROFILE_UPDATECOORDS StarObject::updateCoordsCpuTime = 0.; StarObject::starsUpdated = 0; #endif SkyMap *map = SkyMap::Instance(); KStarsData* data = KStarsData::Instance(); UpdateID updateID = data->updateID(); //FIXME_FOV -- maybe not clamp like that... float radius = map->projector()->fov(); if ( radius > 90.0 ) radius = 90.0; if ( m_skyMesh != SkyMesh::Instance() && m_skyMesh->inDraw() ) { printf("Warning: aborting concurrent DeepStarComponent::draw()"); } bool checkSlewing = ( map->isSlewing() && Options::hideOnSlew() ); //shortcuts to inform whether to draw different objects bool hideFaintStars( checkSlewing && Options::hideStars() ); double hideStarsMag = Options::magLimitHideStar(); //adjust maglimit for ZoomLevel // double lgmin = log10(MINZOOM); // double lgmax = log10(MAXZOOM); // double lgz = log10(Options::zoomFactor()); // TODO: Enable hiding of faint stars float maglim = StarComponent::zoomMagnitudeLimit(); if( maglim < triggerMag ) return; m_zoomMagLimit = maglim; m_skyMesh->inDraw( true ); SkyPoint* focus = map->focus(); m_skyMesh->aperture( focus, radius + 1.0, DRAW_BUF ); // divide by 2 for testing MeshIterator region(m_skyMesh, DRAW_BUF); magLim = maglim; // If we are to hide the fainter stars (eg: while slewing), we set the magnitude limit to hideStarsMag. if( hideFaintStars && maglim > hideStarsMag ) maglim = hideStarsMag; StarBlockFactory *m_StarBlockFactory = StarBlockFactory::Instance(); // m_StarBlockFactory->drawID = m_skyMesh->drawID(); // qDebug() << "Mesh size = " << m_skyMesh->size() << "; drawID = " << m_skyMesh->drawID(); QTime t; int nTrixels = 0; t_dynamicLoad = 0; t_updateCache = 0; t_drawUnnamed = 0; visibleStarCount = 0; t.start(); // Mark used blocks in the LRU Cache. Not required for static stars if( !staticStars ) { while( region.hasNext() ) { Trixel currentRegion = region.next(); for( int i = 0; i < m_starBlockList.at( currentRegion )->getBlockCount(); ++i ) { StarBlock *prevBlock = ( ( i >= 1 ) ? m_starBlockList.at( currentRegion )->block( i - 1 ) : NULL ); StarBlock *block = m_starBlockList.at( currentRegion )->block( i ); if( i == 0 && !m_StarBlockFactory->markFirst( block ) ) qDebug() << "markFirst failed in trixel" << currentRegion; if( i > 0 && !m_StarBlockFactory->markNext( prevBlock, block ) ) qDebug() << "markNext failed in trixel" << currentRegion << "while marking block" << i; if( i < m_starBlockList.at( currentRegion )->getBlockCount() && m_starBlockList.at( currentRegion )->block( i )->getFaintMag() < maglim ) break; } } t_updateCache = t.restart(); region.reset(); } while ( region.hasNext() ) { ++nTrixels; Trixel currentRegion = region.next(); // NOTE: We are guessing that the last 1.5/16 magnitudes in the catalog are just additions and the star catalog // is actually supposed to reach out continuously enough only to mag m_FaintMagnitude * ( 1 - 1.5/16 ) // TODO: Is there a better way? We may have to change the magnitude tolerance if the catalog changes // Static stars need not execute fillToMag if( !staticStars && !m_starBlockList.at( currentRegion )->fillToMag( maglim ) && maglim <= m_FaintMagnitude * ( 1 - 1.5/16 ) ) { qDebug() << "SBL::fillToMag( " << maglim << " ) failed for trixel " << currentRegion << " !"<< endl; } t_dynamicLoad += t.restart(); // qDebug() << "Drawing SBL for trixel " << currentRegion << ", SBL has " // << m_starBlockList[ currentRegion ]->getBlockCount() << " blocks" << endl; // REMARK: The following should never carry state, except for const parameters like updateID and maglim std::function<void( StarBlock * )> mapFunction = [&updateID, &maglim]( StarBlock *myBlock ) { for ( StarObject &star : myBlock->contents() ) { if ( star.updateID != updateID ) star.JITupdate(); if ( star.mag() > maglim ) break; } }; QtConcurrent::blockingMap( m_starBlockList.at( currentRegion )->contents(), mapFunction ); for( int i = 0; i < m_starBlockList.at( currentRegion )->getBlockCount(); ++i ) { StarBlock *block = m_starBlockList.at( currentRegion )->block( i ); // qDebug() << "---> Drawing stars from block " << i << " of trixel " << // currentRegion << ". SB has " << block->getStarCount() << " stars" << endl; for( int j = 0; j < block->getStarCount(); j++ ) { StarObject *curStar = block->star( j ); // qDebug() << "We claim that he's from trixel " << currentRegion //<< ", and indexStar says he's from " << m_skyMesh->indexStar( curStar ); float mag = curStar->mag(); if ( mag > maglim ) break; if( skyp->drawPointSource(curStar, mag, curStar->spchar() ) ) visibleStarCount++; } } // DEBUG: Uncomment to identify problems with Star Block Factory / preservation of Magnitude Order in the LRU Cache // verifySBLIntegrity(); t_drawUnnamed += t.restart(); } m_skyMesh->inDraw( false ); #ifdef PROFILE_SINCOS trig_calls_here += dms::trig_function_calls; trig_redundancy_here += dms::redundant_trig_function_calls; cachingdms_bad_uses += CachingDms::cachingdms_bad_uses; qDebug() << "Spent " << dms::seconds_in_trig << " seconds doing " << trig_calls_here << " trigonometric function calls amounting to an average of " << 1000.0 * dms::seconds_in_trig/double( trig_calls_here ) << " ms per call"; qDebug() << "Redundancy of trig calls in this draw: " << double( trig_redundancy_here ) / double( trig_calls_here ) * 100. << "%"; qDebug() << "CachedDms constructor calls so far: " << CachingDms::cachingdms_constructor_calls; qDebug() << "Caching has prevented " << CachingDms::cachingdms_delta << " redundant trig function calls"; qDebug() << "Bad cache uses in this draw: " << cachingdms_bad_uses; #endif #ifdef PROFILE_UPDATECOORDS qDebug() << "Spent " << StarObject::updateCoordsCpuTime << " seconds updating " << StarObject::starsUpdated << " stars' coordinates (StarObject::updateCoords) for an average of " << double( StarObject::updateCoordsCpuTime )/double( StarObject::starsUpdated ) * 1.e6 << " us per star."; #endif #else Q_UNUSED(skyp) #endif }