static void readLayers(XmlElement* e, WMSLayer* parentLayer, WMSLayer::LayerList& layers) { XmlNodeList layerNodes = e->getSubElements( ELEM_LAYER ); for( XmlNodeList::const_iterator i = layerNodes.begin(); i != layerNodes.end(); i++ ) { XmlElement* e_layer = static_cast<XmlElement*>( i->get() ); WMSLayer *layer = new WMSLayer; layer->setName( e_layer->getSubElementText( ELEM_NAME ) ); layer->setTitle( e_layer->getSubElementText( ELEM_TITLE ) ); layer->setAbstract( e_layer->getSubElementText( ELEM_ABSTRACT ) ); //Read all the supported styles XmlNodeList styles = e_layer->getSubElements( ELEM_STYLE ); for( XmlNodeList::const_iterator styleitr = styles.begin(); styleitr != styles.end(); styleitr++ ) { XmlElement* e_style = static_cast<XmlElement*>( styleitr->get() ); string name = e_style->getSubElementText( ELEM_NAME ); string title = e_style->getSubElementText( ELEM_TITLE ); layer->getStyles().push_back(WMSStyle(name,title)); } //Read all the supported SRS's XmlNodeList spatialReferences = e_layer->getSubElements( ELEM_SRS ); for (XmlNodeList::const_iterator srsitr = spatialReferences.begin(); srsitr != spatialReferences.end(); ++srsitr) { string srs = static_cast<XmlElement*>( srsitr->get() )->getText(); layer->getSpatialReferences().push_back(srs); } //Read all the supported CRS's spatialReferences = e_layer->getSubElements( ELEM_CRS ); for (XmlNodeList::const_iterator srsitr = spatialReferences.begin(); srsitr != spatialReferences.end(); ++srsitr) { string crs = static_cast<XmlElement*>( srsitr->get() )->getText(); layer->getSpatialReferences().push_back(crs); } osg::ref_ptr<XmlElement> e_bb = e_layer->getSubElement( ELEM_LATLONBOUNDINGBOX ); if (e_bb.valid()) { double minX, minY, maxX, maxY; minX = as<double>(e_bb->getAttr( ATTR_MINX ), 0); minY = as<double>(e_bb->getAttr( ATTR_MINY ), 0); maxX = as<double>(e_bb->getAttr( ATTR_MAXX ), 0); maxY = as<double>(e_bb->getAttr( ATTR_MAXY ), 0); layer->setLatLonExtents(minX, minY, maxX, maxY); } else { osg::ref_ptr<XmlElement> e_gbb = e_layer->getSubElement( ELEM_GEOGRAPHICBOUNDINGBOX ); if (e_gbb.valid()) { double minX, minY, maxX, maxY; minX = as<double>(e_gbb->getSubElementText( ATTR_WESTLON ), 0); minY = as<double>(e_gbb->getSubElementText( ATTR_SOUTHLAT ), 0); maxX = as<double>(e_gbb->getSubElementText( ATTR_EASTLON ), 0); maxY = as<double>(e_gbb->getSubElementText( ATTR_NORTHLAT ), 0); layer->setLatLonExtents(minX, minY, maxX, maxY); } } e_bb = e_layer->getSubElement( ELEM_BOUNDINGBOX ); if (e_bb.valid()) { double minX, minY, maxX, maxY; minX = as<double>(e_bb->getAttr( ATTR_MINX ), 0); minY = as<double>(e_bb->getAttr( ATTR_MINY ), 0); maxX = as<double>(e_bb->getAttr( ATTR_MAXX ), 0); maxY = as<double>(e_bb->getAttr( ATTR_MAXY ), 0); layer->setExtents(minX, minY, maxX, maxY); } //Add the layer to the list and set its parent layer layers.push_back(layer); layer->setParentLayer( parentLayer ); //Read any other layers that are in the layer node readLayers( e_layer, layer, layer->getLayers()); } }
/** 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" ); } }
/** 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" ); } }