Esempio n. 1
0
bool
ResourceCache::getOrCreateLineTexture(const URI& uri, osg::ref_ptr<osg::Texture>& output, const osgDB::Options* readOptions)
{
    Threading::ScopedMutexLock lock(_texMutex);
    TextureCache::Record rec;
    if (_texCache.get(uri.full(), rec) && rec.value().valid())
    {
        output = rec.value().get();
    }
    else
    {
        osg::ref_ptr<osg::Image> image = uri.getImage(readOptions);
        if (image.valid())
        {
            osg::Texture2D* tex = new osg::Texture2D(image);
            tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
            tex->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
            tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
            tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
            tex->setMaxAnisotropy( 4.0f );
            tex->setResizeNonPowerOfTwoHint( false );
            output = tex;
            _texCache.insert(uri.full(), output.get());
        }
    }

    return output.valid();
}
Esempio n. 2
0
    void initialize( const std::string& referenceURI, const Profile* overrideProfile)
    {
        if ( !overrideProfile )
        {
            OE_WARN << LC << "An explicit profile definition is required by the OSG driver." << std::endl;
            return;
        }

        setProfile( overrideProfile );

        osg::ref_ptr<osg::Image> image;

        URI url = _options.url().value();
        if ( !url.empty() )
        {
            url = URI( url.full(), referenceURI ); // obselete?
            HTTPClient::ResultCode code = HTTPClient::readImageFile( url.full(), image );
            if ( code != HTTPClient::RESULT_OK )
            {
                OE_WARN << LC << "Failed to load data from \"" << url.full() << "\", because: " << 
                    HTTPClient::getResultCodeString(code) << std::endl;
            }
        }

        if ( !image.valid() )
            OE_WARN << LC << "Faild to load data from \"" << url.full() << "\"" << std::endl;

        // calculate and store the maximum LOD for which to return data
        if ( image.valid() )
        {
            int minSpan = osg::minimum( image->s(), image->t() );
            int tileSize = _options.tileSize().value();
            _maxDataLevel = (int)LOG2((minSpan/tileSize)+1);
            //OE_NOTICE << "[osgEarth::OSG driver] minSpan=" << minSpan << ", _tileSize=" << tileSize << ", maxDataLevel = " << _maxDataLevel << std::endl;

            
            getDataExtents().push_back( DataExtent(overrideProfile->getExtent(), 0, _maxDataLevel) );

            bool computeAlpha =
                (_options.convertLuminanceToRGBA() == true && image->getPixelFormat() == GL_LUMINANCE) ||
                (_options.addAlpha() == true && !ImageUtils::hasAlphaChannel( image.get() ) );

            if ( computeAlpha )
            {
                image = makeRGBAandComputeAlpha( image.get() );
            }
            else if ( ImageUtils::hasAlphaChannel( image.get() ))
            {
                image = ImageUtils::convertToRGBA8( image.get() );
            }
            else
            {
                image = ImageUtils::convertToRGB8( image.get() );
            }

            _image = GeoImage( image.get(), getProfile()->getExtent() );
        }

        _extension = osgDB::getFileExtension( url.full() );
    }
Esempio n. 3
0
    Status initialize(const osgDB::Options* dbOptions)
    {
        _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);        

        URI xyzURI = _options.url().value();
        if ( xyzURI.empty() )
        {
            return Status::Error( "Fail: driver requires a valid \"url\" property" );
        }

        // driver requires a profile.
        if ( !getProfile() )
        {
            return Status::Error( "An explicit profile definition is required by the XYZ driver." );
        }

        _template = xyzURI.full();
        
        _rotateStart = _template.find("[");
        _rotateEnd   = _template.find("]");
        if ( _rotateStart != std::string::npos && _rotateEnd != std::string::npos && _rotateEnd-_rotateStart > 1 )
        {
            _rotateString  = _template.substr(_rotateStart, _rotateEnd-_rotateStart+1);
            _rotateChoices = _template.substr(_rotateStart+1, _rotateEnd-_rotateStart-1);
        }

        _format = _options.format().isSet() 
            ? *_options.format()
            : osgDB::getLowerCaseFileExtension( xyzURI.base() );

        return STATUS_OK;
    }
Esempio n. 4
0
URIStream::URIStream( const URI& uri ) :
_fileStream( 0L )
{
    if ( osgDB::containsServerAddress(uri.full()) )
    {
        HTTPResponse res = HTTPClient::get( uri.full() );
        if ( res.isOK() )
        {
            std::string buf = res.getPartAsString(0);
            _bufStream.str(buf);
        }
    }
    else
    {
        _fileStream = new std::ifstream( uri.full().c_str() );
    }
}
Esempio n. 5
0
URIStream::URIStream(const URI& uri, std::ios_base::openmode mode) :
_instream( 0L )
{
    if ( osgDB::containsServerAddress(uri.full()) )
    {
        HTTPResponse res = HTTPClient::get( uri.full() );
        if ( res.isOK() )
        {
            std::string buf = res.getPartAsString(0);
            _instream = new std::istringstream(buf);
        }
    }
    else
    {
        _instream = new std::ifstream(uri.full().c_str(), mode);
    }
}
Esempio n. 6
0
bool 
ServiceReader::read( const URI& location, const osgDB::Options* options, RESTResponse& response )
{
    response.setServiceURL( location.full() );
    std::string serviceLocation = location.full() + "?f=json&pretty=true";

    ReadResult r = URI(serviceLocation, location.context()).readString();
    if ( r.failed() )
    {
        OE_WARN << "Failed to read ArcGIS Services tile map file from " << serviceLocation << std::endl;
        return false;
    }

    // Read tile map into a Config:
    Config conf;
    std::stringstream buf( r.getString() );
    if (!conf.fromJSON( buf.str() ))
    {
        return false;
    }

    return read( conf, response );    
}
Esempio n. 7
0
KMZArchive::KMZArchive( const URI& archiveURI ) :
_archiveURI( archiveURI ),
_buf( 0L ),
_bufsize( 1024000 )
{
    supportsExtension( "kmz", "KMZ" );

    // download the KMZ to a local cache - cannot open zip files remotely.
    URI localURI( archiveURI );
    if ( osgDB::containsServerAddress(archiveURI.full()) )
    {
        localURI = downloadToCache( archiveURI );
    }

    _uf = unzOpen( localURI.full().c_str() );
    _buf = (void*)new char[_bufsize];
}
Esempio n. 8
0
bool
LandCoverBiome::configure(const ConfigOptions& conf, const osgDB::Options* dbo)
{
    LandCoverBiomeOptions in( conf );

    if ( in.biomeClasses().isSet() )
        setClasses( in.biomeClasses().get() );

    for(SymbolVector::const_iterator i = in.symbols().begin(); i != in.symbols().end(); ++i)
    {
        const BillboardSymbol* bs = dynamic_cast<BillboardSymbol*>( i->get() );
        if ( bs )
        {
            URI imageURI = bs->url()->evalURI();

            osg::Image* image = const_cast<osg::Image*>( bs->getImage() );
            if ( !image )
            {
                image = imageURI.getImage(dbo);
            }

            if ( image )
            {
                getBillboards().push_back( LandCoverBillboard(image, bs->width().get(), bs->height().get()) );
            }
            else
            {
                OE_WARN << LC << "Failed to load billboard image from \"" << imageURI.full() << "\"\n";
            }
        } 
        else
        {
            OE_WARN << LC << "Unrecognized symbol in land cover biome\n";
        }
    }

    if ( getBillboards().size() == 0 )
    {
        OE_WARN << LC << "A biome failed to install any billboards.\n";
        return false;
    }

    return true;
}
bool
SubstituteModelFilter::findResource(const URI&            uri,
                                    const InstanceSymbol* symbol,
                                    FilterContext&        context, 
                                    std::set<URI>&        missing,
                                    osg::ref_ptr<InstanceResource>& output )
{
    // be careful about refptrs here since _instanceCache is an LRU.

    InstanceCache::Record rec;
    if ( _instanceCache.get(uri, rec) )
    {
        // found it in the cache:
        output = rec.value().get();
    }
    else if ( _resourceLib.valid() )
    {
        // look it up in the resource library:
        output = _resourceLib->getInstance( uri.base(), context.getDBOptions() );
    }
    else
    {
        // create it on the fly:
        output = symbol->createResource();
        output->uri() = uri;
        _instanceCache.insert( uri, output.get() );
    }

    // failed to find the instance.
    if ( !output.valid() )
    {
        if ( missing.find(uri) == missing.end() )
        {
            missing.insert(uri);
            OE_WARN << LC << "Failed to locate resource: " << uri.full() << std::endl;
        }
    }

    return output.valid();
}
Esempio n. 10
0
    /** override */
    Status initialize( const osgDB::Options* dbOptions )
    {
        osg::ref_ptr<const Profile> result;

        char sep = _options.url()->full().find_first_of('?') == std::string::npos? '?' : '&';

        URI capUrl = _options.capabilitiesUrl().value();
        if ( capUrl.empty() )
        {
            capUrl = URI(
                _options.url()->full() + 
                sep + 
                std::string("SERVICE=WMS") +
                std::string("&VERSION=") + _options.wmsVersion().value() +
                std::string("&REQUEST=GetCapabilities") );
        }

        //Try to read the WMS capabilities
        osg::ref_ptr<WMSCapabilities> capabilities = WMSCapabilitiesReader::read( capUrl.full(), dbOptions );
        if ( !capabilities.valid() )
        {
            return Status::Error( Status::ResourceUnavailable, "Unable to read WMS GetCapabilities." );
        }
        else
        {
            OE_INFO << LC << "Got capabilities from " << capUrl.full() << std::endl;
        }

        if ( _formatToUse.empty() && capabilities.valid() )
        {
            _formatToUse = capabilities->suggestExtension();
            OE_INFO << LC << "No format specified, capabilities suggested extension " << _formatToUse << std::endl;
        }

        if ( _formatToUse.empty() )
            _formatToUse = "png";
       
        if ( _srsToUse.empty() )
            _srsToUse = "EPSG:4326";

        std::string wmsFormatToUse = _options.wmsFormat().value();

        //Initialize the WMS request prototype
        std::stringstream buf;

        // first the mandatory keys:
        buf
            << std::fixed << _options.url()->full() << sep
	    << "SERVICE=WMS"
            << "&VERSION=" << _options.wmsVersion().value()
            << "&REQUEST=GetMap"
            << "&LAYERS=" << _options.layers().value()
            << "&FORMAT=" << ( wmsFormatToUse.empty() ? std::string("image/") + _formatToUse : wmsFormatToUse )
            << "&STYLES=" << _options.style().value()
            << (_options.wmsVersion().value() == "1.3.0" ? "&CRS=" : "&SRS=") << _srsToUse            
            << "&WIDTH="<< getPixelsPerTile()
            << "&HEIGHT=" << getPixelsPerTile()
            << "&BBOX=%lf,%lf,%lf,%lf";

        // then the optional keys:
        if ( _options.transparent().isSet() )
            buf << "&TRANSPARENT=" << (_options.transparent() == true ? "TRUE" : "FALSE");
            

        _prototype = "";
        _prototype = buf.str();

        //OE_NOTICE << "Prototype " << _prototype << std::endl;

        osg::ref_ptr<SpatialReference> wms_srs = SpatialReference::create( _srsToUse );

        // check for spherical mercator:
        if ( wms_srs.valid() && wms_srs->isEquivalentTo( osgEarth::Registry::instance()->getGlobalMercatorProfile()->getSRS() ) )
        {
            result = osgEarth::Registry::instance()->getGlobalMercatorProfile();
        }
        else if (wms_srs.valid() && wms_srs->isEquivalentTo( osgEarth::Registry::instance()->getGlobalGeodeticProfile()->getSRS()))
        {
            result = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
        }

        // Next, try to glean the extents from the layer list
        if ( capabilities.valid() )
        {
            //TODO: "layers" mights be a comma-separated list. need to loop through and
            //combine the extents?? yes
            WMSLayer* layer = capabilities->getLayerByName( _options.layers().value() );
            if ( layer )
            {
                double minx, miny, maxx, maxy;                
                minx = miny = maxx = maxy = 0;

                //Check to see if the profile is equivalent to global-geodetic
                if (wms_srs->isGeographic())
                {
                    //Try to get the lat lon extents if they are provided
                    layer->getLatLonExtents(minx, miny, maxx, maxy);

                    //If we still don't have any extents, just default to global geodetic.
                    if (!result.valid() && minx == 0 && miny == 0 && maxx == 0 && maxy == 0)
                    {
                        result = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
                    }
                }	

                if (minx == 0 && miny == 0 && maxx == 0 && maxy == 0)
                {
                    layer->getExtents(minx, miny, maxx, maxy);
                }


                if (!result.valid())
                {
                    result = Profile::create( _srsToUse, minx, miny, maxx, maxy );
                }

                //Add the layer extents to the list of valid areas
                if (minx != 0 || maxx != 0 || miny != 0 || maxy != 0)
                {
                    GeoExtent extent( result->getSRS(), minx, miny, maxx, maxy);
                    getDataExtents().push_back( DataExtent(extent, 0) );
                }
            }
        }

        // Last resort: create a global extent profile (only valid for global maps)
        if ( !result.valid() && wms_srs->isGeographic())
        {
            result = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
        }

        // JPL uses an experimental interface called TileService -- ping to see if that's what
        // we are trying to read:
        URI tsUrl = _options.tileServiceUrl().value();
        if ( tsUrl.empty() )
        {
            tsUrl = URI(_options.url()->full() + sep + std::string("request=GetTileService") );
        }

        OE_INFO << LC << "Testing for JPL/TileService at " << tsUrl.full() << std::endl;
        _tileService = TileServiceReader::read(tsUrl.full(), dbOptions);
        if (_tileService.valid())
        {
            OE_INFO << LC << "Found JPL/TileService spec" << std::endl;
            TileService::TilePatternList patterns;
            _tileService->getMatchingPatterns(
                _options.layers().value(),
                _formatToUse,
                _options.style().value(),
                _srsToUse,
                getPixelsPerTile(),
                getPixelsPerTile(),
                patterns );

            if (patterns.size() > 0)
            {
                result = _tileService->createProfile( patterns );
                _prototype = _options.url()->full() + sep + patterns[0].getPrototype();
            }
        }
        else
        {
            OE_INFO << LC << "No JPL/TileService spec found; assuming standard WMS" << std::endl;
        }

        // Use the override profile if one is passed in.
        if ( getProfile() == 0L )
        {
            setProfile( result.get() );
        }

        if ( getProfile() )
        {
            OE_INFO << LC << "Profile=" << getProfile()->toString() << std::endl;

            // set up the cache options properly for a TileSource.
            _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );            

            return Status::OK();
        }
        else
        {
            return Status::Error( "Unable to establish profile" );
        }
    }
Esempio n. 11
0
    /**
     * Create and return an image for the given TileKey.
     */
    osg::Image* createImage( const TileKey& key, ProgressCallback* progress )
    {
        if (_debugDirect)
        {
            //osg::Image* image = new osg::Image;
            //image->allocateImage(256,256,1, GL_RGB, GL_UNSIGNED_BYTE);
            //return image;

            return osgDB::readImageFile( getDirectURI(key) );
            //return URI(getDirectURI(key)).getImage(_dbOptions.get(), progress);
        }

        // center point of the tile (will be in spherical mercator)
        double x, y;
        key.getExtent().getCentroid(x, y);

        // transform it to lat/long:
        GeoPoint geo;

        GeoPoint( getProfile()->getSRS(), x, y ).transform(
            getProfile()->getSRS()->getGeographicSRS(),
            geo );

        // contact the REST API. Docs are here:
        // http://msdn.microsoft.com/en-us/library/ff701716.aspx

        // construct the request URI:
        std::string request = Stringify()
            << std::setprecision(12)
            << _options.imageryMetadataAPI().get()     // base REST API
            << "/"    << _options.imagerySet().get()   // imagery set to use
            << "/"    << geo.y() << "," << geo.x()     // center point in lat/long
            << "?zl=" << key.getLOD() + 1              // zoom level
            << "&o=json"                               // response format
            << "&key=" << _options.key().get();        // API key

        // check the URI cache.
        URI                  location;
        TileURICache::Record rec;

        if ( _tileURICache.get(request, rec) )
        {
            location = URI(rec.value());
            //CacheStats stats = _tileURICache.getStats();
            //OE_INFO << "Ratio = " << (stats._hitRatio*100) << "%" << std::endl;
        }
        else
        {
            unsigned c = ++_apiCount;
            if ( c % 25 == 0 )
                OE_INFO << LC << "API calls = " << c << std::endl;
            
            // fetch it:
            ReadResult metadataResult = URI(request).readString(_dbOptions, progress);

            if ( metadataResult.failed() )
            {
                // check for a REST error:
                if ( metadataResult.code() == ReadResult::RESULT_SERVER_ERROR )
                {
                    OE_WARN << LC << "REST API request error!" << std::endl;

                    Config metadata;
                    std::string content = metadataResult.getString();
                    metadata.fromJSON( content );
                    ConfigSet errors = metadata.child("errorDetails").children();
                    for(ConfigSet::const_iterator i = errors.begin(); i != errors.end(); ++i )
                    {
                        OE_WARN << LC << "REST API: " << i->value() << std::endl;
                    }
                    return 0L;
                }
                else
                {
                    OE_WARN << LC << "Request error: " << metadataResult.getResultCodeString() << std::endl;
                }
                return 0L;
            }

            // decode it:
            Config metadata;
            if ( !metadata.fromJSON(metadataResult.getString()) )
            {
                OE_WARN << LC << "Error decoding REST API response" << std::endl;
                return 0L;
            }

            // check the vintage field. If it's empty, that means we got a "no data" tile.
            Config* vintageEnd = metadata.find("vintageEnd");
            if ( !vintageEnd || vintageEnd->value().empty() )
            {
                OE_DEBUG << LC << "NO data image encountered." << std::endl;
                return 0L;
            }

            // find the tile URI:
            Config* locationConf= metadata.find("imageUrl");
            if ( !locationConf )
            {
                OE_WARN << LC << "REST API JSON parsing error (imageUrl not found)" << std::endl;
                return 0L;
            }

            location = URI( locationConf->value() );
            _tileURICache.insert( request, location.full() );
        }

        // request the actual tile
        //OE_INFO << "key = " << key.str() << ", URL = " << location->value() << std::endl;

        //osg::Image* image = location.getImage(_dbOptions.get(), progress);
        osg::Image* image = osgDB::readImageFile( location.full() );

        if ( image &&  _geom.valid() )
        {
            GeometryRasterizer rasterizer( image->s(), image->t() );
            rasterizer.draw( _geom.get(), osg::Vec4(1,1,1,1) );
            osg::ref_ptr<osg::Image> overlay = rasterizer.finalize();
            ImageUtils::PixelVisitor<AlphaBlend> blend;
            blend.accept( overlay.get(), image );
        }

        return image;
    }
Esempio n. 12
0
    // override
    Status initialize( const osgDB::Options* dbOptions )
    {
        // add the security token to the URL if necessary:
        URI url = _options.url().value();

		OE_DEBUG << LC << "Initial URL: " << url.full() << std::endl;

		// append token to url in query string is set
        if (_options.token().isSet())
        {
            std::string token = _options.token().value();
            if (!token.empty())
            {
                std::string sep = url.full().find( "?" ) == std::string::npos ? "?" : "&";
                url = url.append( sep + std::string("token=") + token );
            }
        }
		else
		{
			OE_DEBUG << LC << "Token not set" << std::endl;
		}

		// append layers to url in query string is set .. format is show:1,2,3
		if (_options.layers().isSet())
        {
			std::string layers = _options.layers().value();
			OE_DEBUG << LC << "_Layers: " << layers << std::endl;
			if (!layers.empty())
			{
				std::string sep = url.full().find( "?" ) == std::string::npos ? "?" : "&";
				url = url.append( sep + std::string("layers=show:") + layers );
			}
		}
		else
		{
			OE_DEBUG << LC << "Layer options not set" << std::endl;
		}

		OE_DEBUG << LC << "_map_service URL: " << url.full() << std::endl;

        // read map service metadata from the server
        if ( !_map_service.init(url, dbOptions) )
        {
			OE_INFO << LC << "_map_service.init failed: " << _map_service.getError() << std::endl;

            return Status::Error( Stringify()
                << "[osgearth] [ArcGIS] map service initialization failed: "
                << _map_service.getError() );
        }

        _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );        

        // establish a profile if we don't already have one:
        if ( !getProfile() )
        {
            const Profile* profile = NULL;

            if ( _profileConf.isSet() )
            {
                profile = Profile::create( _profileConf.get() );
            }
            else if ( _map_service.getProfile() )
            {
                profile = _map_service.getProfile();
            }
            else
            {
                // finally, fall back on lat/long
                profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
            }
            setProfile( profile );
        }

        return STATUS_OK;
    }
Esempio n. 13
0
void
ModelNode::init()
{
    // reset.
    this->clearDecoration();
    osgEarth::clearChildren( this );
    osgEarth::clearChildren( _xform.get() );
    this->addChild( _xform.get() );

    this->setHorizonCulling(false);

    osg::ref_ptr<const ModelSymbol> sym = _style.get<ModelSymbol>();
    
    // backwards-compatibility: support for MarkerSymbol (deprecated)
    if ( !sym.valid() && _style.has<MarkerSymbol>() )
    {
        osg::ref_ptr<InstanceSymbol> temp = _style.get<MarkerSymbol>()->convertToInstanceSymbol();
        sym = dynamic_cast<const ModelSymbol*>( temp.get() );
    }

    if ( sym.valid() )
    {
        if ( ( sym->url().isSet() ) || (sym->getModel() != NULL) )
        {
            // Try to get a model from symbol
            osg::ref_ptr<osg::Node> node = sym->getModel();

            // Try to get a model from URI
            if (node.valid() == false)
            {
                URI uri = sym->url()->evalURI();

                if ( sym->uriAliasMap()->empty() )
                {
                    node = uri.getNode( _dbOptions.get() );
                }
                else
                {
                    // install an alias map if there's one in the symbology.
                    osg::ref_ptr<osgDB::Options> tempOptions = Registry::instance()->cloneOrCreateOptions(_dbOptions.get());
                    tempOptions->setReadFileCallback( new URIAliasMapReadCallback(*sym->uriAliasMap(), uri.full()) );
                    node = uri.getNode( tempOptions.get() );
                }

                if (node.valid() == false)
                {
                    OE_WARN << LC << "No model and failed to load data from " << uri.full() << std::endl;
                }
            }

            if (node.valid() == true)
            {
                if ( Registry::capabilities().supportsGLSL() )
                {
                    // generate shader code for the loaded model:
                    Registry::shaderGenerator().run(
                        node.get(),
                        "osgEarth.ModelNode",
                        Registry::stateSetCache() );
                }

                // attach to the transform:
                _xform->addChild( node );

                // insert a clamping agent if necessary:
                replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) );

                if ( sym->scale().isSet() )
                {
                    double s = sym->scale()->eval();
                    this->setScale( osg::Vec3f(s, s, s) );
                }

                // auto scaling?
                if ( sym->autoScale() == true )
                {
                    this->getOrCreateStateSet()->setRenderBinDetails(0, osgEarth::AUTO_SCALE_BIN );
                }

                // rotational offsets?
                if (sym && (sym->heading().isSet() || sym->pitch().isSet() || sym->roll().isSet()) )
                {
                    osg::Matrix rot;
                    double heading = sym->heading().isSet() ? sym->heading()->eval() : 0.0;
                    double pitch   = sym->pitch().isSet()   ? sym->pitch()->eval()   : 0.0;
                    double roll    = sym->roll().isSet()    ? sym->roll()->eval()    : 0.0;
                    rot.makeRotate( 
                        osg::DegreesToRadians(heading), osg::Vec3(0,0,1),
                        osg::DegreesToRadians(pitch),   osg::Vec3(1,0,0),
                        osg::DegreesToRadians(roll),    osg::Vec3(0,1,0) );
                    this->setLocalRotation( rot.getRotate() );
                }

                this->applyRenderSymbology( _style );
            }
            else
            {
                OE_WARN << LC << "No model" << std::endl;
            }
        }
        else
        {
            OE_WARN << LC << "Symbology: no URI or model" << std::endl;
        }
    }
    else
    {
        OE_WARN << LC << "Insufficient symbology" << std::endl;
    }
}
Esempio n. 14
0
    // one-time initialization (per source)
    Status initialize(const osgDB::Options* dbOptions)
    {
        _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);

        const Profile* profile = getProfile();

        URI tmsURI = _options.url().value();
        if ( tmsURI.empty() )
        {
            return Status::Error( "Fail: TMS driver requires a valid \"url\" property" );
        }

        // Take the override profile if one is given
        if ( profile )
        {
            OE_INFO << LC
                    << "Using override profile \"" << getProfile()->toString()
                    << "\" for URI \"" << tmsURI.base() << "\""
                    << std::endl;

            _tileMap = TMS::TileMap::create(
                           _options.url()->full(),
                           profile,
                           _options.format().value(),
                           _options.tileSize().value(),
                           _options.tileSize().value() );
        }

        else
        {
            // Attempt to read the tile map parameters from a TMS TileMap XML tile on the server:
            _tileMap = TMS::TileMapReaderWriter::read( tmsURI.full(), _dbOptions.get() );
            if (!_tileMap.valid())
            {
                return Status::Error( Stringify() << "Failed to read tilemap from " << tmsURI.full() );
            }

            OE_INFO << LC
                    << "TMS tile map datestamp = "
                    << DateTime(_tileMap->getTimeStamp()).asRFC1123()
                    << std::endl;

            profile = _tileMap->createProfile();
            if ( profile )
                setProfile( profile );
        }

        // Make sure we've established a profile by this point:
        if ( !profile )
        {
            return Status::Error( Stringify() << "Failed to establish a profile for " << tmsURI.full() );
        }

        // TileMap and profile are valid at this point. Build the tile sets.
        // Automatically set the min and max level of the TileMap
        if ( _tileMap->getTileSets().size() > 0 )
        {
            OE_DEBUG << LC << "TileMap min/max " << _tileMap->getMinLevel() << ", " << _tileMap->getMaxLevel() << std::endl;
            if (_tileMap->getDataExtents().size() > 0)
            {
                for (DataExtentList::iterator itr = _tileMap->getDataExtents().begin(); itr != _tileMap->getDataExtents().end(); ++itr)
                {
                    this->getDataExtents().push_back(*itr);
                }
            }
            else
            {
                //Push back a single area that encompasses the whole profile going up to the max level
                this->getDataExtents().push_back(DataExtent(profile->getExtent(), 0, _tileMap->getMaxLevel()));
            }
        }

        // set up the IO options so that we do not cache TMS tiles:
        CachePolicy::NO_CACHE.apply( _dbOptions.get() );

        return STATUS_OK;
    }
Esempio n. 15
0
    /** override */
    Status initialize( const osgDB::Options* dbOptions )
    {
        osg::ref_ptr<const Profile> result;

        char sep = _options.url()->full().find_first_of('?') == std::string::npos? '?' : '&';

        URI capUrl = _options.capabilitiesUrl().value();
        if ( capUrl.empty() )
        {
            capUrl = URI(
                _options.url()->full() + 
                sep + 
                std::string("SERVICE=WMS") +
                std::string("&VERSION=") + _options.wmsVersion().value() +
                std::string("&REQUEST=GetCapabilities") );
        }

        //Try to read the WMS capabilities
        osg::ref_ptr<WMSCapabilities> capabilities = WMSCapabilitiesReader::read( capUrl, dbOptions );
        if ( !capabilities.valid() )
        {
            return Status::Error( Status::ResourceUnavailable, "Unable to read WMS GetCapabilities." );
        }
        else
        {
            OE_INFO << LC << "Got capabilities from " << capUrl.full() << std::endl;
        }

        if ( _formatToUse.empty() && capabilities.valid() )
        {
            _formatToUse = capabilities->suggestExtension();
            OE_INFO << LC << "No format specified, capabilities suggested extension " << _formatToUse << std::endl;
        }

        if ( _formatToUse.empty() )
            _formatToUse = "png";
       
        if ( _srsToUse.empty() )
            _srsToUse = "EPSG:4326";

        std::string wmsFormatToUse = _options.wmsFormat().value();

        //Initialize the WMS request prototype
        std::stringstream buf;

        // first the mandatory keys:
        buf
            << std::fixed << _options.url()->full() << sep
	    << "SERVICE=WMS"
            << "&VERSION=" << _options.wmsVersion().value()
            << "&REQUEST=GetMap"
            << "&LAYERS=" << _options.layers().value()
            << "&FORMAT=" << ( wmsFormatToUse.empty() ? std::string("image/") + _formatToUse : wmsFormatToUse )
            << "&STYLES=" << _options.style().value()
            << (_options.wmsVersion().value() == "1.3.0" ? "&CRS=" : "&SRS=") << _srsToUse            
            << "&WIDTH="<< getPixelsPerTile()
            << "&HEIGHT=" << getPixelsPerTile()
            << "&BBOX=%lf,%lf,%lf,%lf";

        // then the optional keys:
        if ( _options.transparent().isSet() )
            buf << "&TRANSPARENT=" << (_options.transparent() == true ? "TRUE" : "FALSE");
            

        _prototype = "";
        _prototype = buf.str();

        //OE_NOTICE << "Prototype " << _prototype << std::endl;

        osg::ref_ptr<SpatialReference> wms_srs = SpatialReference::create( _srsToUse );

        // check for spherical mercator:
        if ( wms_srs.valid() && wms_srs->isEquivalentTo( osgEarth::Registry::instance()->getSphericalMercatorProfile()->getSRS() ) )
        {
            result = osgEarth::Registry::instance()->getSphericalMercatorProfile();
        }
        else if (wms_srs.valid() && wms_srs->isEquivalentTo( osgEarth::Registry::instance()->getGlobalGeodeticProfile()->getSRS()))
        {
            result = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
        }

        // Next, try to glean the extents from the layer list
        if ( capabilities.valid() )
        {
            StringTokenizer tok(",");
            StringVector tized;
            tok.tokenize(_options.layers().value(), tized);

            for (StringVector::const_iterator itr = tized.begin(); itr != tized.end(); ++itr)
            {
                std::string layerName = *itr;
                WMSLayer* layer = capabilities->getLayerByName(layerName);
                if (layer)
                {
                    // Get the lat/lon extents
                    double minLon, minLat, maxLon, maxLat;
                    layer->getLatLonExtents(minLon, minLat, maxLon, maxLat);
                    GeoExtent wgs84Extent(SpatialReference::create("wgs84"), minLon, minLat, maxLon, maxLat);
                    getDataExtents().push_back(DataExtent(wgs84Extent, 0));
                }
            }

            // If we don't have a profile yet, transform the lat/lon extents to the requested srs and use it as the extents of the profile.
            if (!result.valid())
            {
                const SpatialReference* srs = SpatialReference::create(_srsToUse);
                GeoExtent totalExtent(srs);
                for (DataExtentList::const_iterator itr = getDataExtents().begin(); itr != getDataExtents().end(); ++itr)
                {
                    GeoExtent dataExtent = *itr;
                    GeoExtent nativeExtent;
                    dataExtent.transform(srs, nativeExtent);
                    totalExtent.expandToInclude(nativeExtent);
                }
                result = Profile::create(srs, totalExtent.xMin(), totalExtent.yMin(), totalExtent.xMax(), totalExtent.yMax());
            }
        }

        // Last resort: create a global extent profile (only valid for global maps)
        if ( !result.valid() && wms_srs->isGeographic())
        {
            result = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
        }    

#ifdef SUPPORT_JPL_TILESERVICE
        // JPL uses an experimental interface called TileService -- ping to see if that's what
        // we are trying to read:
        URI tsUrl = _options.tileServiceUrl().value();
        if ( tsUrl.empty() )
        {
            tsUrl = URI(_options.url()->full() + sep + std::string("request=GetTileService"), tsUrl.context());
        }

        OE_INFO << LC << "Testing for JPL/TileService at " << tsUrl.full() << std::endl;
        osg::ref_ptr<TileService> tileService = TileServiceReader::read(tsUrl.full(), dbOptions);
        if (tileService.valid())
        {
            OE_INFO << LC << "Found JPL/TileService spec" << std::endl;
            TileService::TilePatternList patterns;
            tileService->getMatchingPatterns(
                _options.layers().value(),
                _formatToUse,
                _options.style().value(),
                _srsToUse,
                getPixelsPerTile(),
                getPixelsPerTile(),
                patterns );

            if (patterns.size() > 0)
            {
                result = tileService->createProfile( patterns );
                _prototype = _options.url()->full() + sep + patterns[0].getPrototype();
            }
        }
        else
        {
            OE_INFO << LC << "No JPL/TileService spec found; assuming standard WMS" << std::endl;
        }
#endif

        // Use the override profile if one is passed in.
        if ( getProfile() == 0L )
        {
            setProfile( result.get() );
        }

        if ( getProfile() )
        {
            OE_INFO << LC << "Profile=" << getProfile()->toString() << std::endl;

            // set up the cache options properly for a TileSource.
            _dbOptions = Registry::instance()->cloneOrCreateOptions( dbOptions );            

            return Status::OK();
        }
        else
        {
            return Status::Error( "Unable to establish profile" );
        }
    }
Esempio n. 16
0
Status
TMSTileSource::initialize(const osgDB::Options* dbOptions)
{
    // local copy of options we can modify if necessary.
    _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);

    // see if the use passed in a profile
    const Profile* profile = getProfile();

    // URI is mandatory.
    URI tmsURI = _options.url().value();
    if ( tmsURI.empty() )
    {
        return Status::Error( Status::ConfigurationError, "Fail: TMS driver requires a valid \"url\" property" );
    }

    // A repo is writable only if it's local.
    if ( tmsURI.isRemote() )
    {
        OE_DEBUG << LC << "Repo is remote; opening in read-only mode" << std::endl;
    }

    // Is this a new repo? (You can only create a new repo at a local non-archive URI.)
    bool isNewRepo = false;

    if (!tmsURI.isRemote() && 
        !osgEarth::isPathToArchivedFile(tmsURI.full()) &&
        !osgDB::fileExists(tmsURI.full()) )
    {
        isNewRepo = true;

        // new repo REQUIRES a profile:
        if ( !profile )
        {
            return Status::Error(Status::ConfigurationError, "Fail: profile required to create new TMS repo");
        }
    }

    // Take the override profile if one is given
    if ( profile )
    {
        OE_INFO << LC 
            << "Using express profile \"" << getProfile()->toString() 
            << "\" for URI \"" << tmsURI.base() << "\"" 
            << std::endl;

        DataExtentList extents;

        _tileMap = TMS::TileMap::create( 
            _options.url()->full(),
            profile,
            extents,
            _options.format().value(),
            256,
            256);
            //getPixelsPerTile(),
            //getPixelsPerTile() );

        // If this is a new repo, write the tilemap file to disk now.
        if ( isNewRepo )
        {
            if ( !_options.format().isSet() )
            {
                return Status::Error(Status::ConfigurationError, "Missing required \"format\" property: e.g. png, jpg");
            }

            TMS::TileMapReaderWriter::write( _tileMap.get(), tmsURI.full() );
            OE_INFO << LC << "Created new TMS repo at " << tmsURI.full() << std::endl;
        }
    }

    else
    {
        // Attempt to read the tile map parameters from a TMS TileMap XML tile on the server:
        _tileMap = TMS::TileMapReaderWriter::read( tmsURI.full(), _dbOptions.get() );

        if (!_tileMap.valid())
        {
            return Status::Error( Status::ResourceUnavailable, Stringify() << "Failed to read configuration from " << tmsURI.full() );
        }

        OE_INFO << LC
            << "TMS tile map datestamp = "
            << DateTime(_tileMap->getTimeStamp()).asRFC1123()
            << std::endl;

        profile = _tileMap->createProfile();
        if ( profile )
            setProfile( profile );
    }

    // Make sure we've established a profile by this point:
    if ( !profile )
    {
        return Status::Error( Stringify() << "Failed to establish a profile for " << tmsURI.full() );
    }

    // resolve the writer
    if ( !tmsURI.isRemote() && !resolveWriter() )
    {
        OE_WARN << LC << "Cannot create writer; writing disabled" << std::endl;
    }

    // TileMap and profile are valid at this point. Build the tile sets.
    // Automatically set the min and max level of the TileMap
    if ( _tileMap->getTileSets().size() > 0 )
    {
        OE_DEBUG << LC << "TileMap min/max " << _tileMap->getMinLevel() << ", " << _tileMap->getMaxLevel() << std::endl;
        if (_tileMap->getDataExtents().size() > 0)
        {
            for (DataExtentList::iterator itr = _tileMap->getDataExtents().begin(); itr != _tileMap->getDataExtents().end(); ++itr)
            {
                this->getDataExtents().push_back(*itr);
            }
        }        
    }
    return STATUS_OK;
}