Example #1
0
Profile::Profile(const SpatialReference* srs,
                 double xmin, double ymin, double xmax, double ymax,
                 double geo_xmin, double geo_ymin, double geo_xmax, double geo_ymax,
                 unsigned int numTilesWideAtLod0,
                 unsigned int numTilesHighAtLod0 ) :

osg::Referenced( true )
{
    _extent = GeoExtent( srs, xmin, ymin, xmax, ymax );

    _numTilesWideAtLod0 = numTilesWideAtLod0 != 0? numTilesWideAtLod0 : srs->isGeographic()? 2 : 1;
    _numTilesHighAtLod0 = numTilesHighAtLod0 != 0? numTilesHighAtLod0 : 1;

    _latlong_extent = GeoExtent( 
        srs->getGeographicSRS(),
        geo_xmin, geo_ymin, geo_xmax, geo_ymax );

    //if ( !_vsrs.valid() )
    //    _vsrs = Registry::instance()->getDefaultVSRS();

    // make a profile sig (sans srs) and an srs sig for quick comparisons.
    ProfileOptions temp = toProfileOptions();
    _fullSignature = Stringify() << std::hex << hashString( temp.getConfig().toJSON() );
    temp.vsrsString() = "";
    _horizSignature = Stringify() << std::hex << hashString( temp.getConfig().toJSON() );
}
Example #2
0
const Profile*
TerrainLayer::getProfile() const
{
    // NB: in cache-only mode, there IS NO layer profile.
    if ( !_profile.valid() && !isCacheOnly() )
    {
        if ( !_tileSourceInitAttempted )
        {
            // Call getTileSource to make sure the TileSource is initialized
            getTileSource();
        }

        if ( _tileSource.valid() && !_profile.valid() && !_tileSourceInitFailed )
        {
            const_cast<TerrainLayer*>(this)->_profile = _tileSource->getProfile();

            // check for a vertical datum override:
            if ( _profile.valid() && _runtimeOptions->verticalDatum().isSet() )
            {
                std::string vdatum = toLower( *_runtimeOptions->verticalDatum() );
                if ( _profile->getSRS()->getVertInitString() != vdatum )
                {
                    ProfileOptions po = _profile->toProfileOptions();
                    po.vsrsString() = vdatum;
                    const_cast<TerrainLayer*>(this)->_profile = Profile::create(po);
                }
            }
        }
    }
    
    return _profile.get();
}
Example #3
0
Profile::Profile(const SpatialReference* srs,
                 double xmin, double ymin, double xmax, double ymax,
                 unsigned int numTilesWideAtLod0,
                 unsigned int numTilesHighAtLod0) :

osg::Referenced( true )
{
    _extent = GeoExtent( srs, xmin, ymin, xmax, ymax );

    _numTilesWideAtLod0 = numTilesWideAtLod0 != 0? numTilesWideAtLod0 : srs->isGeographic()? 2 : 1;
    _numTilesHighAtLod0 = numTilesHighAtLod0 != 0? numTilesHighAtLod0 : 1;

    // automatically calculate the lat/long extents:
    _latlong_extent = srs->isGeographic()?
        _extent :
        _extent.transform( _extent.getSRS()->getGeographicSRS() );

    // make a profile sig (sans srs) and an srs sig for quick comparisons.
    ProfileOptions temp = toProfileOptions();
    _fullSignature = Stringify() << std::hex << hashString( temp.getConfig().toJSON() );
    temp.vsrsString() = "";
    _horizSignature = Stringify() << std::hex << hashString( temp.getConfig().toJSON() );
}
Example #4
0
void
TerrainLayer::applyProfileOverrides()
{
    // Check for a vertical datum override.
    bool changed = false;
    if ( _profile.valid() && _runtimeOptions->verticalDatum().isSet() )
    {
        std::string vdatum = *_runtimeOptions->verticalDatum();
        OE_INFO << "override vdatum = " << vdatum << ", profile vdatum = " << _profile->getSRS()->getVertInitString() << std::endl;
        if ( !ciEquals(_profile->getSRS()->getVertInitString(), vdatum) )
        {
            ProfileOptions po = _profile->toProfileOptions();
            po.vsrsString() = vdatum;
            _profile = Profile::create(po);
            changed = true;
        }
    }

    if (changed && _profile.valid())
    {
        OE_INFO << LC << "Override profile: " << _profile->toString() << std::endl;
    }
}
Example #5
0
ProfileOptions
Profile::toProfileOptions() const
{
    ProfileOptions op;
    op.srsString() = getSRS()->getHorizInitString();
    op.vsrsString() = getSRS()->getVertInitString();
    op.bounds()->xMin() = _extent.xMin();
    op.bounds()->yMin() = _extent.yMin();
    op.bounds()->xMax() = _extent.xMax();
    op.bounds()->yMax() = _extent.yMax();
    op.numTilesWideAtLod0() = _numTilesWideAtLod0;
    op.numTilesHighAtLod0() = _numTilesHighAtLod0;
    return op;
}
Example #6
0
void
TerrainLayer::initTileSource()
{
    _tileSourceInitAttempted = true;

    OE_DEBUG << LC << "Initializing tile source ..." << std::endl;

    // Instantiate it from driver options if it has not already been created.
    // This will also set a manual "override" profile if the user provided one.
    if ( !_tileSource.valid() )
    {
        if ( _runtimeOptions->driver().isSet() )
        {
            _tileSource = TileSourceFactory::create(*_runtimeOptions->driver());
        }
    }

    // Initialize the profile with the context information:
    if ( _tileSource.valid() )
    {
        // set up the URI options.
        if ( !_dbOptions.valid() )
        {
            _dbOptions = Registry::instance()->cloneOrCreateOptions();
            if ( _cache.valid() ) _cache->apply( _dbOptions.get() );
            _initOptions.cachePolicy()->apply( _dbOptions.get() );
            URIContext( _runtimeOptions->referrer() ).apply( _dbOptions.get() );
        }


        // report on a manual override profile:
        if ( _tileSource->getProfile() )
        {
            OE_INFO << LC << "set profile to: " 
                << _tileSource->getProfile()->toString() << std::endl;
        }

        // Open the tile source (if it hasn't already been started)
        TileSource::Status status = _tileSource->getStatus();
        if ( status != TileSource::STATUS_OK )
        {
            status = _tileSource->open(TileSource::MODE_READ, _dbOptions.get());
        }

        if ( status == TileSource::STATUS_OK )
        {
            _tileSize = _tileSource->getPixelsPerTile();

#if 0 //debugging 
            // dump out data extents:
            if ( _tileSource->getDataExtents().size() > 0 )
            {
                OE_INFO << LC << "Data extents reported:" << std::endl;
                for(DataExtentList::const_iterator i = _tileSource->getDataExtents().begin();
                    i != _tileSource->getDataExtents().end(); ++i)
                {
                    const DataExtent& de = *i;
                    OE_INFO << "    "
                        << "X(" << i->xMin() << ", " << i->xMax() << ") "
                        << "Y(" << i->yMin() << ", " << i->yMax() << ") "
                        << "Z(" << i->minLevel().get() << ", " << i->maxLevel().get() << ")"
                        << std::endl;
                }                
            }
#endif
        }
        else
        {
            OE_WARN << LC << "Could not initialize driver" << std::endl;
            _tileSource = NULL;
            _tileSourceInitFailed = true;
            _runtimeOptions->enabled() = true;
        }
    }

    // Set the profile from the TileSource if possible:
    if ( _tileSource.valid() )
    {
        if ( !_profile.valid() && !_tileSourceInitFailed )
        {
            _profile = _tileSource->getProfile();
        }

        // check for a vertical datum override:
        if ( _profile.valid() && _runtimeOptions->verticalDatum().isSet() )
        {
            std::string vdatum = *_runtimeOptions->verticalDatum();
            if ( !ciEquals(_profile->getSRS()->getVertInitString(), vdatum) )
            {
                OE_INFO << LC << "Overriding vdatum with: " << vdatum << std::endl;
                ProfileOptions po = _profile->toProfileOptions();
                po.vsrsString() = vdatum;
                _profile = Profile::create(po);
            }
        }

        if ( _profile.valid() )
        {
            OE_INFO << LC << "Profile=" << _profile->toString() << std::endl;
        }
    }

    // Otherwise, force cache-only mode (since there is no tilesource). The layer will try to 
    // establish a profile from the metadata in the cache instead.
    else if (_cache.valid())
    {
        OE_NOTICE << LC << "Could not initialize TileSource " << _name << ", but a cache exists. Setting layer to cache-only mode." << std::endl;
        setCachePolicy( CachePolicy::CACHE_ONLY );
    }
}
Example #7
0
/**
 * Command-line tool that copies the contents of one TileSource
 * to another. All arguments are Config name/value pairs, so you need
 * to look in the header file for each driver's Options structure for
 * options :)
 *
 * Example: copy a GDAL file to an MBTiles repo:
 *
 *   osgearth_conv
 *      --in driver gdal
 *      --in url world.tif
 *      --out driver mbtiles
 *      --out filename world.db
 *
 * The "in" properties come from the GDALOptions getConfig method. The
 * "out" properties come from the MBTilesOptions getConfig method.
 *
 * Other arguments:
 *
 *      --elevation           : convert as elevation data (instead of image data)
 *      --profile [profile]   : reproject to the target profile, e.g. "wgs84"
 *      --min-level [int]     : min level of detail to copy
 *      --max-level [int]     : max level of detail to copy
 *      --threads [n]         : threads to use (may crash. Careful.)
 *
 *      --extents [minLat] [minLong] [maxLat] [maxLong] : Lat/Long extends to copy (*)
 *
 * Of course, the output driver must support writing (by implementing
 * the ReadWriteTileSource interface).
 */
int
main(int argc, char** argv)
{
    osg::ArgumentParser args(&argc,argv);

    if ( argc == 1 )
        return usage(argv);

    typedef std::map<std::string,std::string> KeyValue;
    std::string key, value;

    // collect input configuration:
    Config inConf;
    while( args.read("--in", key, value) )
        inConf.set(key, value);

    TileSourceOptions inOptions(inConf);
    osg::ref_ptr<TileSource> input = TileSourceFactory::create(inOptions);
    if ( !input.valid() )
    {
        OE_WARN << LC << "Failed to open input" << std::endl;
        return -1;
    }

    TileSource::Status inputStatus = input->open();
    if ( inputStatus.isError() )
    {
        OE_WARN << LC << "Error initializing input" << std::endl;
        return -1;
    }

    // collect output configuration:
    Config outConf;
    while( args.read("--out", key, value) )
        outConf.set(key, value);

    // heightfields?
    bool heightFields = args.read("--heightfield") || args.read("--hf") || args.read("--elevation");
    if ( heightFields )
        OE_INFO << LC << "Converting heightfield tiles" << std::endl;
    else
        OE_INFO << LC << "Converting image tiles" << std::endl;

    // are we changing profiles?
    osg::ref_ptr<const Profile> outputProfile = input->getProfile();
    std::string profileString;
    bool isSameProfile = true;

    if ( args.read("--profile", profileString) )
    {
        outputProfile = Profile::create(profileString);
        if ( !outputProfile.valid() || !outputProfile->isOK() )
        {
            OE_WARN << LC << "Output profile is not recognized" << std::endl;
            return -1;
        }
        isSameProfile = outputProfile->isHorizEquivalentTo(input->getProfile());
    }

    // set the output profile.
    ProfileOptions profileOptions = outputProfile->toProfileOptions();
    outConf.add("profile", profileOptions.getConfig());

    // open the output tile source:
    TileSourceOptions outOptions(outConf);
    osg::ref_ptr<TileSource> output = TileSourceFactory::create(outOptions);
    if ( !output.valid() )
    {
        OE_WARN << LC << "Failed to open output" << std::endl;
        return -1;
    }

    TileSource::Status outputStatus = output->open(TileSource::MODE_WRITE | TileSource::MODE_CREATE);
    if ( outputStatus.isError() )
    {
        OE_WARN << LC << "Error initializing output" << std::endl;
        return -1;
    }

    // Dump out some stuff...
    OE_NOTICE << LC << "FROM:\n"
        << inConf.toJSON(true)
        << std::endl;

    OE_NOTICE << LC << "TO:\n"
        << outConf.toJSON(true)
        << std::endl;

    // create the visitor.
    osg::ref_ptr<TileVisitor> visitor;

    unsigned numThreads = 1;
    if (args.read("--threads", numThreads))
    {
        MultithreadedTileVisitor* mtv = new MultithreadedTileVisitor();
        mtv->setNumThreads( numThreads < 1 ? 1 : numThreads );
        visitor = mtv;
    }
    else
    {
        visitor = new TileVisitor();
    }

    // If the profiles are identical, just use a tile copier.
    if ( isSameProfile )
    {
        OE_NOTICE << LC << "Profiles match - initiating simple tile copy" << std::endl;
        visitor->setTileHandler( new TileSourceToTileSource(input.get(), output.get(), heightFields) );
    }
    else
    {
        OE_NOTICE << LC << "Profiles differ - initiating tile transformation" << std::endl;

        if (heightFields)
        {
            ElevationLayer* layer = new ElevationLayer(ElevationLayerOptions(), input.get());
            if ( !layer->getProfile() || !layer->getProfile()->isOK() )
            {
                OE_WARN << LC << "Input profile is not valid" << std::endl;
                return -1;
            }
            visitor->setTileHandler( new ElevationLayerToTileSource(layer, output.get()) );
        }
        else
        {
            ImageLayer* layer = new ImageLayer(ImageLayerOptions(), input.get());
            if ( !layer->getProfile() || !layer->getProfile()->isOK() )
            {
                OE_WARN << LC << "Input profile is not valid" << std::endl;
                return -1;
            }
            visitor->setTileHandler( new ImageLayerToTileSource(layer, output.get()) );
        }
    }
    
    // Set the level limits:
    unsigned minLevel = ~0;
    bool minLevelSet = args.read("--min-level", minLevel);

    unsigned maxLevel = 0;
    bool maxLevelSet = args.read("--max-level", maxLevel);

    // figure out the max source level:
    if ( !minLevelSet || !maxLevelSet )
    {
        for(DataExtentList::const_iterator i = input->getDataExtents().begin();
            i != input->getDataExtents().end();
            ++i)
        {
            if ( !maxLevelSet && i->maxLevel().isSet() && i->maxLevel().value() > maxLevel )
                maxLevel = i->maxLevel().value();
            if ( !minLevelSet && i->minLevel().isSet() && i->minLevel().value() < minLevel )
                minLevel = i->minLevel().value();
        }
    }
       
    if ( minLevel < ~0 )
    {
        visitor->setMinLevel( minLevel );
    }

    if ( maxLevel > 0 )
    {
        maxLevel = outputProfile->getEquivalentLOD( input->getProfile(), maxLevel );
        visitor->setMaxLevel( maxLevel );
        OE_NOTICE << LC << "Calculated max level = " << maxLevel << std::endl;
    }

    // set the extents:
    double minlat, minlon, maxlat, maxlon;
    while( args.read("--extents", minlat, minlon, maxlat, maxlon) )
    {
        GeoExtent extent(SpatialReference::get("wgs84"), minlon, minlat, maxlon, maxlat);
        visitor->addExtent( extent );
    }

    // Ready!!!
    std::cout << "Working..." << std::endl;

    visitor->setProgressCallback( new ProgressReporter() );

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

    visitor->run( outputProfile.get() );

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

    std::cout
        << "Time = " 
        << std::fixed
        << std::setprecision(1)
        << osg::Timer::instance()->delta_s(t0, t1)
        << " seconds." << std::endl;

    return 0;
}
Example #8
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;
        }
    }
}