예제 #1
0
Status
LandUseTileSource::initialize(const osgDB::Options* dbOptions)
{
    _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);

    const Profile* profile = getProfile();
    if ( !profile )
    {
        profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
        setProfile( profile );
    }

    // load all the image layers:
    _imageLayers.assign( _options.imageLayerOptionsVector().size(), 0L );
    _warps.assign( _options.imageLayerOptionsVector().size(), 0.0f );

    for(unsigned i=0; i<_options.imageLayerOptionsVector().size(); ++i)
    {
        ImageLayerOptions ilo = _options.imageLayerOptionsVector()[i];
        ilo.cachePolicy() = CachePolicy::NO_CACHE;
        ImageLayer* layer = new ImageLayer( ilo );
        layer->setTargetProfileHint( profile );
        layer->setReadOptions(_dbOptions.get());
        layer->open();
        _imageLayers[i] = layer;

        Config conf = ilo.getConfig();
        _warps[i] = conf.value("warp", _options.warpFactor().get());
    }

    // set up the noise generator.
    const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f };
    const float P[4] = { 0.8f,  0.6f, 0.8f, 0.9f };
    const float L[4] = { 2.2f,  1.7f, 3.0f, 4.0f };
    
    // Configure the noise function:
    _noiseGen.setNormalize  ( true );
    _noiseGen.setRange      ( 0.0, 1.0 );
    _noiseGen.setFrequency  ( F[0] );
    _noiseGen.setPersistence( P[0] );
    _noiseGen.setLacunarity ( L[0] );
    _noiseGen.setOctaves    ( 8 );

    return STATUS_OK;
}
예제 #2
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 format image/png
 *      --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 (*)
 *
 * OSG arguments:
 *
 *      -O <string>           : OSG Options string (plugin options)
 *
 * 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);

    osg::ref_ptr<osgDB::Options> dbo = new osgDB::Options();

    // plugin options, if the user passed them in:
    std::string str;
    while(args.read("--osg-options", str) || args.read("-O", str))
    {
        dbo->setOptionString( str );
    }

    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;
    }

    Status inputStatus = input->open( input->MODE_READ, dbo.get() );
    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;
    }

    // Copy over the data extents to the output datasource.
    for (DataExtentList::const_iterator itr = input->getDataExtents().begin(); itr != input->getDataExtents().end(); ++itr)
    {
        // Convert the data extent to the profile that is actually used by the output tile source
        DataExtent dataExtent = *itr;
        GeoExtent ext = dataExtent.transform(outputProfile->getSRS());
        unsigned int minLevel = 0;
        unsigned int maxLevel = outputProfile->getEquivalentLOD( input->getProfile(), *dataExtent.maxLevel() );
        DataExtent outputExtent = DataExtent(ext, minLevel, maxLevel);
        output->getDataExtents().push_back( outputExtent );
    }

    Status outputStatus = output->open(
        TileSource::MODE_WRITE | TileSource::MODE_CREATE,
        dbo.get() );

    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());
            Status layerStatus = layer->open();
            if (layerStatus.isError())
            {
                OE_WARN << "Failed to create input ElevationLayer " << layerStatus.message() << std::endl;
                return -1;
            }
            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());
            Status layerStatus = layer->open();
            if (layerStatus.isError())
            {
                OE_WARN << "Failed to create input ImageLayer " << layerStatus.message() << std::endl;
                return -1;
            }
            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;
}