Пример #1
0
void CacheSeed::seed( Map* map )
{
    // We must do this to avoid an error message in OpenSceneGraph b/c the findWrapper method doesn't appear to be threadsafe.
    // This really isn't a big deal b/c this only effects data that is already cached.
    osgDB::ObjectWrapper* wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper( "osg::Image" );

    osg::Timer_t startTime = osg::Timer::instance()->tick();
    if ( !map->getCache() )
    {
        OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl;
        return;
    }

    std::vector<TileKey> keys;
    map->getProfile()->getRootKeys(keys);

    //Add the map's entire extent if we don't have one specified.
    if (_extents.empty())
    {
        addExtent( map->getProfile()->getExtent() );
    }

    bool hasCaches = false;
    int src_min_level = INT_MAX;
    unsigned int src_max_level = 0;

    MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" );

    //Assumes the the TileSource will perform the caching for us when we call createImage
    for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ )
    {
        ImageLayer* layer = i->get();
        TileSource* src   = layer->getTileSource();

        const ImageLayerOptions& opt = layer->getImageLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if ( !src )
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ )
    {
        ElevationLayer* layer = i->get();
        TileSource*     src   = layer->getTileSource();
        const ElevationLayerOptions& opt = layer->getElevationLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if (!src)
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    if ( !hasCaches )
    {
        OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl;
        return;
    }

    if ( src_max_level > 0 && src_max_level < _maxLevel )
    {
        _maxLevel = src_max_level;
    }

    OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl;

    //Estimate the number of tiles
    _total = 0;    
    CacheEstimator est;
    est.setMinLevel( _minLevel );
    est.setMaxLevel( _maxLevel );
    est.setProfile( map->getProfile() ); 
    for (unsigned int i = 0; i < _extents.size(); i++)
    {                
        est.addExtent( _extents[ i ] );
    } 
    _total = est.getNumTiles();

    OE_INFO << "Processing ~" << _total << " tiles" << std::endl;


    // Initialize the operations queue
    _queue = new osg::OperationQueue;

    osg::Timer_t endTime = osg::Timer::instance()->tick();

    // Start the threads
    std::vector< osg::ref_ptr< osg::OperationsThread > > threads;
    for (unsigned int i = 0; i < _numThreads; i++)
    {        
        osg::OperationsThread* thread = new osg::OperationsThread();
        thread->setOperationQueue(_queue.get());
        thread->start();
        threads.push_back( thread );
    }

    OE_NOTICE << "Startup time " << osg::Timer::instance()->delta_s( startTime, endTime ) << std::endl;

    
    // Add the root keys to the queue
    for (unsigned int i = 0; i < keys.size(); ++i)
    {
        //processKey( mapf, keys[i] );
        _queue.get()->add( new CacheTileOperation( mapf, *this, keys[i]) );
    }    

    bool done = false;
    while (!done)
    {
        OpenThreads::Thread::microSleep(500000); // sleep for half a second
        done = true;
        if (_queue->getNumOperationsInQueue() > 0)
        {
            done = false;
            continue;
        }
        else
        {
            // Make sure no threads are currently working on an operation, which actually might add MORE operations since we are doing a quadtree traversal
            for (unsigned int i = 0; i < threads.size(); i++)
            {
                if (threads[i]->getCurrentOperation())
                {
                    done = false;
                    continue;
                }
            }
        }
    }    

    _total = _completed;

    if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished");
}
Пример #2
0
osg::Image*
CompositeTileSource::createImage(const TileKey&    key,
                                 ProgressCallback* progress )
{    
    ImageMixVector images;
    images.reserve(_imageLayers.size());

    // Try to get an image from each of the layers for the given key.
    for (ImageLayerVector::const_iterator itr = _imageLayers.begin(); itr != _imageLayers.end(); ++itr)
    {
        ImageLayer* layer = itr->get();
        ImageInfo imageInfo;
        imageInfo.dataInExtents = layer->getTileSource()->hasDataInExtent( key.getExtent() );
        imageInfo.opacity = layer->getOpacity();

        if (imageInfo.dataInExtents)
        {
            GeoImage image = layer->createImage(key, progress);
            if (image.valid())
            {
                imageInfo.image = image.getImage();
            }

            // If the progress got cancelled or it needs a retry then return NULL to prevent this tile from being built and cached with incomplete or partial data.
            if (progress && (progress->isCanceled() || progress->needsRetry()))
            {
                OE_DEBUG << LC << " createImage was cancelled or needs retry for " << key.str() << std::endl;
                return 0L;
            }
        }

        images.push_back(imageInfo);
    }

    // Determine the output texture size to use based on the image that were creatd.
    unsigned numValidImages = 0;
    osg::Vec2s textureSize;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid())
        {
            if (numValidImages == 0)
            {
                textureSize.set( info.image->s(), info.image->t());
            }
            numValidImages++;        
        }
    } 

    // Create fallback images if we have some valid data but not for all the layers
    if (numValidImages > 0 && numValidImages < images.size())
    {
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            ImageLayer* layer = _imageLayers[i].get();
            if (!info.image.valid() && info.dataInExtents)
            {                      
                TileKey parentKey = key.createParentKey();

                GeoImage image;
                while (!image.valid() && parentKey.valid())
                {
                    image = layer->createImage(parentKey, progress);
                    if (image.valid())
                    {
                        break;
                    }

                    // If the progress got cancelled or it needs a retry then return NULL to prevent this tile from being built and cached with incomplete or partial data.
                    if (progress && (progress->isCanceled() || progress->needsRetry()))
                    {
                        OE_DEBUG << LC << " createImage was cancelled or needs retry for " << key.str() << std::endl;
                        return 0L;
                    }

                    parentKey = parentKey.createParentKey();
                }

                if (image.valid())
                {                                        
                    // TODO:  Bilinear options?
                    bool bilinear = layer->isCoverage() ? false : true;
                    GeoImage cropped = image.crop( key.getExtent(), true, textureSize.x(), textureSize.y(), bilinear);
                    info.image = cropped.getImage();
                }                    
            }
        }
    }

    // Now finally create the output image.
    //Recompute the number of valid images
    numValidImages = 0;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid()) numValidImages++;        
    }    

    if ( progress && progress->isCanceled() )
    {
        return 0L;
    }
    else if ( numValidImages == 0 )
    {
        return 0L;
    }
    else if ( numValidImages == 1 )
    {
        //We only have one valid image, so just return it and don't bother with compositing
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            if (info.image.valid())
                return info.image.release();
        }
        return 0L;
    }
    else
    {
        osg::Image* result = 0;
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& imageInfo = images[i];
            if (!result)
            {
                if (imageInfo.image.valid())
                {
                    result = new osg::Image( *imageInfo.image.get());
                }
            }
            else
            {
                if (imageInfo.image.valid())
                {
                    ImageUtils::mix( result, imageInfo.image.get(), imageInfo.opacity );
                }
            }            
        }        
        return result;
    }



}
Пример #3
0
void CacheSeed::seed( Map* map )
{
    if ( !map->getCache() )
    {
        OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl;
        return;
    }

    std::vector<TileKey> keys;
    map->getProfile()->getRootKeys(keys);

    //Add the map's entire extent if we don't have one specified.
    if (_extents.empty())
    {
        addExtent( map->getProfile()->getExtent() );
    }

    bool hasCaches = false;
    int src_min_level = INT_MAX;
    unsigned int src_max_level = 0;

    MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" );

    //Assumes the the TileSource will perform the caching for us when we call createImage
    for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ )
    {
        ImageLayer* layer = i->get();
        TileSource* src   = layer->getTileSource();

        const ImageLayerOptions& opt = layer->getImageLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if ( !src )
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ )
    {
        ElevationLayer* layer = i->get();
        TileSource*     src   = layer->getTileSource();
        const ElevationLayerOptions& opt = layer->getElevationLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if (!src)
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    if ( !hasCaches )
    {
        OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl;
        return;
    }

    if ( src_max_level > 0 && src_max_level < _maxLevel )
    {
        _maxLevel = src_max_level;
    }

    OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl;

    //Estimate the number of tiles
    _total = 0;    
    CacheEstimator est;
    est.setMinLevel( _minLevel );
    est.setMaxLevel( _maxLevel );
    est.setProfile( map->getProfile() ); 
    for (unsigned int i = 0; i < _extents.size(); i++)
    {                
        est.addExtent( _extents[ i ] );
    } 
    _total = est.getNumTiles();

    OE_INFO << "Processing ~" << _total << " tiles" << std::endl;

    for (unsigned int i = 0; i < keys.size(); ++i)
    {
        processKey( mapf, keys[i] );
    }

    _total = _completed;

    if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished");
}
Пример #4
0
void
Map::calculateProfile()
{
    if ( !_profile.valid() )
    {
        osg::ref_ptr<const Profile> userProfile;
        if ( _mapOptions.profile().isSet() )
        {
            userProfile = Profile::create( _mapOptions.profile().value() );
        }

        if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC )
        {
            if ( userProfile.valid() )
            {
                if ( userProfile->isOK() && userProfile->getSRS()->isGeographic() )
                {
                    _profile = userProfile.get();
                }
                else
                {
                    OE_WARN << LC 
                        << "Map is geocentric, but the configured profile SRS ("
                        << userProfile->getSRS()->getName() << ") is not geographic; "
                        << "it will be ignored."
                        << std::endl;
                }
            }

            if ( !_profile.valid() )
            {
                // by default, set a geocentric map to use global-geodetic WGS84.
                _profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
            }
        }

        else if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE )
        {
            //If the map type is a Geocentric Cube, set the profile to the cube profile.
            _profile = osgEarth::Registry::instance()->getCubeProfile();
        }

        else // CSTYPE_PROJECTED
        {
            if ( userProfile.valid() )
            {
                _profile = userProfile.get();
            }
        }

        // At this point, if we don't have a profile we need to search tile sources until we find one.
        if ( !_profile.valid() )
        {
            Threading::ScopedReadLock lock( _mapDataMutex );

            for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end() && !_profile.valid(); i++ )
            {
                ImageLayer* layer = i->get();
                if ( layer->getTileSource() )
                {
                    _profile = layer->getTileSource()->getProfile();
                }
            }

            for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end() && !_profile.valid(); i++ )
            {
                ElevationLayer* layer = i->get();
                if ( layer->getTileSource() )
                {
                    _profile = layer->getTileSource()->getProfile();
                }
            }
        }

        // convert the profile to Plate Carre if necessary.
        if (_profile.valid() &&
            _profile->getSRS()->isGeographic() && 
            getMapOptions().coordSysType() == MapOptions::CSTYPE_PROJECTED )
        {
            OE_INFO << LC << "Projected display with geographic SRS; activating Plate Carre mode" << std::endl;
            _profile = _profile->overrideSRS( _profile->getSRS()->createPlateCarreGeographicSRS() );
        }

        // finally, fire an event if the profile has been set.
        if ( _profile.valid() )
        {
            OE_INFO << LC << "Map profile is: " << _profile->toString() << std::endl;

            for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
            {
                i->get()->onMapInfoEstablished( MapInfo(this) );
            }
        }

        else
        {
            OE_WARN << LC << "Warning, not yet able to establish a map profile!" << std::endl;
        }
    }

    if ( _profile.valid() )
    {
        // tell all the loaded layers what the profile is, as a hint
        {
            Threading::ScopedWriteLock lock( _mapDataMutex );

            for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); i++ )
            {
                ImageLayer* layer = i->get();
                if ( layer->getEnabled() == true )
                {
                    layer->setTargetProfileHint( _profile.get() );
                }
            }

            for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); i++ )
            {
                ElevationLayer* layer = i->get();
                if ( layer->getEnabled() )
                {
                    layer->setTargetProfileHint( _profile.get() );
                }
            }
        }

        // create a "proxy" profile to use when querying elevation layers with a vertical datum
        if ( _profile->getSRS()->getVerticalDatum() != 0L )
        {
            ProfileOptions po = _profile->toProfileOptions();
            po.vsrsString().unset();
            _profileNoVDatum = Profile::create(po);
        }
        else
        {
            _profileNoVDatum = _profile;
        }
    }
}
Пример #5
0
void CacheSeed::seed( Map* map )
{
    if ( !map->getCache() )
    {
        OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl;
        return;
    }

    std::vector<TileKey> keys;
    map->getProfile()->getRootKeys(keys);

    //Add the map's entire extent if we don't have one specified.
    if (_extents.empty())
    {
        addExtent( map->getProfile()->getExtent() );
    }

    bool hasCaches = false;
    int src_min_level = INT_MAX;
    unsigned int src_max_level = 0;

    MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" );

    //Assumes the the TileSource will perform the caching for us when we call createImage
    for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ )
    {
        ImageLayer* layer = i->get();
        TileSource* src   = layer->getTileSource();

        const ImageLayerOptions& opt = layer->getImageLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if ( !src )
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ )
    {
        ElevationLayer* layer = i->get();
        TileSource*     src   = layer->getTileSource();
        const ElevationLayerOptions& opt = layer->getElevationLayerOptions();

        if ( layer->isCacheOnly() )
        {
            OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl;
        }
        else if (!src)
        {
            OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl;
        }
        //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE )
        //{
        //    OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl;
        //}
        else if ( !layer->getCache() )
        {
            OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl;
        }
        else
        {
            hasCaches = true;

            if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
                src_min_level = opt.minLevel().get();
            if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
                src_max_level = opt.maxLevel().get();
        }
    }

    if ( !hasCaches )
    {
        OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl;
        return;
    }

    if ( src_max_level > 0 && src_max_level < _maxLevel )
    {
        _maxLevel = src_max_level;
    }

    OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl;

    osg::Timer_t startTime = osg::Timer::instance()->tick();
    //Estimate the number of tiles
    _total = 0;    

    for (unsigned int level = _minLevel; level <= _maxLevel; level++)
    {
        double coverageRatio = 0.0;

        if (_extents.empty())
        {
            unsigned int wide, high;
            map->getProfile()->getNumTiles( level, wide, high );
            _total += (wide * high);
        }
        else
        {
            for (std::vector< GeoExtent >::const_iterator itr = _extents.begin(); itr != _extents.end(); itr++)
            {
                const GeoExtent& extent = *itr;
                double boundsArea = extent.area();

                TileKey ll = map->getProfile()->createTileKey(extent.xMin(), extent.yMin(), level);
                TileKey ur = map->getProfile()->createTileKey(extent.xMax(), extent.yMax(), level);

                if (!ll.valid() || !ur.valid()) continue;
                
                int tilesWide = ur.getTileX() - ll.getTileX() + 1;
                int tilesHigh = ll.getTileY() - ur.getTileY() + 1;
                int tilesAtLevel = tilesWide * tilesHigh;
                //OE_NOTICE << "Tiles at level " << level << "=" << tilesAtLevel << std::endl;

                /*
                bool hasData = false;
                
                for (ImageLayerVector::const_iterator itr = mapf.imageLayers().begin(); itr != mapf.imageLayers().end(); itr++)
                {
                    TileSource* src = itr->get()->getTileSource();
                    if (src)
                    {
                        if (src->hasDataAtLOD( level ))
                        {
                            //Compute the percent coverage of this dataset on the current extent
                            if (src->getDataExtents().size() > 0)
                            {
                                double cov = 0.0;
                                for (unsigned int j = 0; j < src->getDataExtents().size(); j++)
                                {
                                    GeoExtent b = src->getDataExtents()[j].transform( extent.getSRS());
                                    GeoExtent intersection = b.intersectionSameSRS( extent );
                                    if (intersection.isValid())
                                    {
                                        double coverage = intersection.area() / boundsArea;
                                        cov += coverage; //Assumes the extents aren't overlapping                            
                                    }
                                }
                                if (coverageRatio < cov) coverageRatio = cov;
                            }
                            else
                            {
                                //We have no way of knowing how much coverage we have
                                coverageRatio = 1.0;
                            }
                            hasData = true;
                            break;
                        }
                    }
                }

                for (ElevationLayerVector::const_iterator itr = mapf.elevationLayers().begin(); itr != mapf.elevationLayers().end(); itr++)
                {
                    TileSource* src = itr->get()->getTileSource();
                    if (src)
                    {
                        if (src->hasDataAtLOD( level ))
                        {
                            //Compute the percent coverage of this dataset on the current extent
                            if (src->getDataExtents().size() > 0)
                            {
                                double cov = 0.0;
                                for (unsigned int j = 0; j < src->getDataExtents().size(); j++)
                                {
                                    GeoExtent b = src->getDataExtents()[j].transform( extent.getSRS());
                                    GeoExtent intersection = b.intersectionSameSRS( extent );
                                    if (intersection.isValid())
                                    {
                                        double coverage = intersection.area() / boundsArea;
                                        cov += coverage; //Assumes the extents aren't overlapping                            
                                    }
                                }
                                if (coverageRatio < cov) coverageRatio = cov;
                            }
                            else
                            {
                                //We have no way of knowing how much coverage we have
                                coverageRatio = 1.0;
                            }
                            hasData = true;
                            break;
                        }
                    }
                }

                //Adjust the coverage ratio by a fudge factor to try to keep it from being too small,
                //tiles are either processed or not and the ratio is exact so will cover tiles partially
                //and potentially be too small
                double adjust = 4.0;
                coverageRatio = osg::clampBetween(coverageRatio * adjust, 0.0, 1.0);                

                //OE_NOTICE << level <<  " CoverageRatio = " << coverageRatio << std::endl;

                if (hasData)
                {
                    _total += (int)ceil(coverageRatio * (double)tilesAtLevel );
                }
                */
                _total += tilesAtLevel;
            }
        }
    }

    osg::Timer_t endTime = osg::Timer::instance()->tick();
    //OE_NOTICE << "Counted tiles in " << osg::Timer::instance()->delta_s(startTime, endTime) << " s" << std::endl;

    OE_INFO << "Processing ~" << _total << " tiles" << std::endl;

    for (unsigned int i = 0; i < keys.size(); ++i)
    {
        processKey( mapf, keys[i] );
    }

    _total = _completed;

    if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished");
}
Пример #6
0
void
Map::calculateProfile()
{
    if ( !_profile.valid() )
    {
        osg::ref_ptr<const Profile> userProfile;
        if ( _mapOptions.profile().isSet() )
        {
            userProfile = Profile::create( _mapOptions.profile().value() );
        }

        if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC )
        {
            if ( userProfile.valid() )
            {
                if ( userProfile->isOK() && userProfile->getSRS()->isGeographic() )
                {
                    _profile = userProfile.get();
                }
                else
                {
                    OE_WARN << LC 
                        << "Map is geocentric, but the configured profile does not "
                        << "have a geographic SRS. Falling back on default.."
                        << std::endl;
                }
            }

            if ( !_profile.valid() )
            {
                // by default, set a geocentric map to use global-geodetic WGS84.
                _profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
            }
        }

        else if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE )
        {
            //If the map type is a Geocentric Cube, set the profile to the cube profile.
            _profile = osgEarth::Registry::instance()->getCubeProfile();
        }

        else // CSTYPE_PROJECTED
        {
            if ( userProfile.valid() )
            {
                _profile = userProfile.get();
            }
        }

        // At this point, if we don't have a profile we need to search tile sources until we find one.
        if ( !_profile.valid() )
        {
            Threading::ScopedReadLock lock( _mapDataMutex );

            for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end() && !_profile.valid(); i++ )
            {
                ImageLayer* layer = i->get();
                if ( layer->getTileSource() )
                {
                    _profile = layer->getTileSource()->getProfile();
                }
            }

            for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end() && !_profile.valid(); i++ )
            {
                ElevationLayer* layer = i->get();
                if ( layer->getTileSource() )
                {
                    _profile = layer->getTileSource()->getProfile();
                }
            }
        }

        // finally, fire an event if the profile has been set.
        if ( _profile.valid() )
        {
            OE_INFO << LC << "Map profile is: " << _profile->toString() << std::endl;

            for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
            {
                i->get()->onMapInfoEstablished( MapInfo(this) );
            }
        }

        else
        {
            OE_WARN << LC << "Warning, not yet able to establish a map profile!" << std::endl;
        }
    }

    if ( _profile.valid() )
    {
        // tell all the loaded layers what the profile is, as a hint
        {
            Threading::ScopedWriteLock lock( _mapDataMutex );

            for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); i++ )
            {
                ImageLayer* layer = i->get();
                layer->setTargetProfileHint( _profile.get() );
            }

            for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); i++ )
            {
                ElevationLayer* layer = i->get();
                layer->setTargetProfileHint( _profile.get() );
            }
        }
    }
}