예제 #1
0
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 );
    }
}
예제 #2
0
// 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
}