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; }
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() ); }
void CPlotter::set_data_set(const URI &uri) { cf3_assert ( !uri.empty() ); cf3_assert ( uri.scheme() == URI::Scheme::CPATH ); m_data = uri; }
void NLink::set_target_path(const URI & path) { if(!path.empty()) { Handle< CNode > target(access_component_checked(path)); this->set_target_node(target); } }
void GraphicalUriArray::btAddClicked() { if(m_editAdd->text().isEmpty()) { if(m_comboType->currentText() == "cpath") { SelectPathDialog spd; QString modified_path = m_editAdd->text(); URI path = spd.show(modified_path.toStdString()); if(!path.empty()) m_editAdd->setText( path.string().c_str() ); } else if(m_comboType->currentText() == "file") { NRemoteOpen::Ptr nro = NRemoteOpen::create(); QStringList fileList = nro->showMultipleSelect(""); QStringList::iterator file = fileList.begin(); for( ; file != fileList.end() ; ++ file) { file->prepend( m_comboType->currentText() + ':' ); } if(!fileList.isEmpty()) m_model->setStringList( m_model->stringList() << fileList ); } } if(!m_editAdd->text().isEmpty()) { QString pathStr = m_editAdd->text(); if( !pathStr.startsWith(m_comboType->currentText()) ) pathStr.prepend(m_comboType->currentText() + ':'); m_model->setStringList( m_model->stringList() << pathStr ); m_editAdd->clear(); } emit valueChanged(); }
void C3DViewBuilder::signal_create_3dview(SignalArgs &args) { SignalOptions options( args ); std::string name = options.value<std::string>("3DView name"); URI parent = options.value<URI>("Parent"); // some checks if(name.empty()) throw BadValue(FromHere(), "The 3DView name is empty."); if(parent.empty()) throw BadValue(FromHere(), "The parent is empty."); if(parent.scheme() != URI::Scheme::CPATH) throw InvalidURI(FromHere(), "The parent scheme is not CPATH"); // create and add the component Handle<Component> parent_comp = Core::instance().root().access_component(parent); Handle<C3DView> view = parent_comp->create_component<C3DView>( name ); view->mark_basic(); }
void CPlotter::signal_create_xyplot(SignalArgs &args) { SignalOptions options( args ); std::string name = options.value<std::string>("Plot name"); URI parent = options.value<URI>("Parent"); // some checks if(name.empty()) throw BadValue(FromHere(), "The plot name is empty."); if(parent.empty()) throw BadValue(FromHere(), "The parent is empty."); if(parent.scheme() != URI::Scheme::CPATH) throw InvalidURI(FromHere(), "The parent scheme is not CPATH"); // create and add the component Handle< Component > parent_comp = Core::instance().root().access_component(parent); boost::shared_ptr< CPlotXY > plot(common::allocate_component<CPlotXY>(name)); parent_comp->add_component( plot ); plot->mark_basic(); plot->set_data(m_data); }
bool JSONAPI::handlePage(HTTP::WebContext &ctx, ostream &stream, const URI &uri) { if (!String::startsWith(uri.getPath(), root)) return false; string cmd = uri.getPath().substr(root.length()); // Look up command api_t::const_iterator it = api.find(cmd); if (it == api.end()) return false; ctx.setDynamic(); // Don't cache HTTP::Connection &con = ctx.getConnection(); bool jsonp = !jsonpCB.empty() && uri.has(jsonpCB); if (jsonp) { con.getResponse().setContentType("application/javascript"); con << uri.get(jsonpCB) << '('; } else con.getResponse().setContentType("application/json"); JSON::Writer writer(con, 0, !uri.has("pretty"), uri.has("python_mode") ? JSON::Writer::PYTHON_MODE : JSON::Writer::JSON_MODE); try { // Parse JSON data JSON::ValuePtr msg; if (con.getRequest().hasContentType() && String::startsWith(con.getRequest().getContentType(), "application/json")) { MemoryBuffer &payload = con.getPayload(); if (payload.getFill()) msg = JSON::Reader(payload).parse(); } else if (!uri.empty()) { msg = new JSON::Dict; for (URI::const_iterator it = uri.begin(); it != uri.end(); it++) msg->insert(it->first, it->second); } // Dispatch API command if (msg.isNull()) LOG_DEBUG(5, "JSONAPI Call: " << cmd << "()"); else LOG_DEBUG(5, "JSONAPI Call: " << cmd << '(' << *msg << ')'); it->second->handle(ctx, cmd, msg, writer); // Make sure JSON stream is complete writer.close(); } catch (const Exception &e) { LOG_ERROR(e); // Clear possibly partial or invalid response con.clearResponseBuffer(); // jsonp header if (jsonp) con << uri.get(jsonpCB) << '('; // Send error message JSON::Writer writer(con, 0, true); writer.beginList(); writer.append("error"); writer.append(e.getMessage()); writer.endList(); writer.close(); } if (jsonp) con << ");"; return true; }
std::istream* HTTPStreamFactory::open(const URI& uri) { poco_assert (uri.getScheme() == "http"); URI resolvedURI(uri); URI proxyUri; HTTPClientSession* pSession = 0; HTTPResponse res; bool retry = false; bool authorize = false; std::string username; std::string password; try { do { if (!pSession) { pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort()); if (proxyUri.empty()) pSession->setProxy(_proxyHost, _proxyPort); else pSession->setProxy(proxyUri.getHost(), proxyUri.getPort()); pSession->setProxyCredentials(_proxyUsername, _proxyPassword); } std::string path = resolvedURI.getPathAndQuery(); if (path.empty()) path = "/"; HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); if (authorize) { HTTPCredentials::extractCredentials(uri, username, password); HTTPCredentials cred(username, password); cred.authenticate(req, res); } pSession->sendRequest(req); std::istream& rs = pSession->receiveResponse(res); bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || res.getStatus() == HTTPResponse::HTTP_FOUND || res.getStatus() == HTTPResponse::HTTP_SEE_OTHER || res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT); if (moved) { resolvedURI.resolve(res.get("Location")); if (!username.empty()) { resolvedURI.setUserInfo(username + ":" + password); } throw URIRedirection(resolvedURI.toString()); } else if (res.getStatus() == HTTPResponse::HTTP_OK) { return new HTTPResponseStream(rs, pSession); } else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry) { // The requested resource MUST be accessed through the proxy // given by the Location field. The Location field gives the // URI of the proxy. The recipient is expected to repeat this // single request via the proxy. 305 responses MUST only be generated by origin servers. // only use for one single request! proxyUri.resolve(res.get("Location")); delete pSession; pSession = 0; retry = true; // only allow useproxy once } else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize) { authorize = true; retry = true; Poco::NullOutputStream null; Poco::StreamCopier::copyStream(rs, null); } else throw HTTPException(res.getReason(), uri.toString()); } while (retry); throw HTTPException("Too many redirects", uri.toString()); } catch (...) { delete pSession; throw; } }
// 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; }
void PlaceNode::init(const osgDB::Options* dbOptions) { _geode = new osg::Geode(); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) _text = _style.get<TextSymbol>()->content()->eval(); osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = URI( icon->url()->eval(), icon->url()->uriContext() ); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( dbOptions ); } } // found an image; now format it: if ( _image.get() ) { // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, (_image->t() / 2.0)); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((_image->s() / 2.0), -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((_image->s() / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((_image->s() / 2.0), (_image->t() / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (_image->t() / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(_image->s() / 2.0), -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(_image->s() / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(_image->s() / 2.0), (_image->t() / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading ); if ( imageGeom ) _geode->addDrawable( imageGeom ); text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( (offset.x() + (_image->s() / 2.0) + 2), offset.y(), 0 ) ); } else { text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( 0, 0, 0 ) ); } if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getAttachPoint()->addChild( _geode ); // for clamping applyStyle( _style ); setLightingIfNotSet( false ); ShaderGenerator gen( Registry::stateSetCache() ); this->accept( gen ); }
/** 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" ); } }
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; }
void PlaceNode::init() { Decluttering::setEnabled( this->getOrCreateStateSet(), true ); osgEarth::clearChildren( getPositionAttitudeTransform() ); _geode = new osg::Geode(); // ensure that (0,0,0) is the bounding sphere control/center point. // useful for things like horizon culling. _geode->setComputeBoundingSphereCallback(new ControlPointCallback()); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) { _text = _style.get<TextSymbol>()->content()->eval(); } osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) { instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); } const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = icon->url()->evalURI(); } else if (icon->getImage()) { _image = icon->getImage(); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( _dbOptions.get() ); } } osg::BoundingBox imageBox(0,0,0,0,0,0); // found an image; now format it: if ( _image.get() ) { // Scale the icon if necessary double scale = 1.0; if ( icon && icon->scale().isSet() ) { scale = icon->scale()->eval(); } double s = scale * _image->s(); double t = scale * _image->t(); // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, t / 2.0); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((s / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((s / 2.0), (t / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(t / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(s / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(s / 2.0), (t / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale ); if ( imageGeom ) { _geode->addDrawable( imageGeom ); imageBox = osgEarth::Utils::getBoundingBox( imageGeom ); } } if ( _image.valid() ) { TextSymbol* textSymbol = _style.getOrCreate<TextSymbol>(); if ( !textSymbol->alignment().isSet() ) textSymbol->alignment() = textSymbol->ALIGN_LEFT_CENTER; } text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), imageBox ); if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getPositionAttitudeTransform()->addChild( _geode ); // for clamping and occlusion culling //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl; applyStyle( _style ); setLightingIfNotSet( false ); // generate shaders: Registry::shaderGenerator().run( this, "osgEarth.PlaceNode", Registry::stateSetCache() ); setPriority(getPriority()); if ( _dynamic ) setDynamic( _dynamic ); updateLayoutData(); }
void PlaceNode::init() { //reset. this->clearDecoration(); getAttachPoint()->removeChildren(0, getAttachPoint()->getNumChildren()); _geode = new osg::Geode(); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) { _text = _style.get<TextSymbol>()->content()->eval(); } osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) { instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); } const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = URI( icon->url()->eval(), icon->url()->uriContext() ); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( _dbOptions.get() ); } } // found an image; now format it: if ( _image.get() ) { // Scale the icon if necessary double scale = 1.0; if ( icon && icon->scale().isSet() ) { scale = icon->scale()->eval(); } double s = scale * _image->s(); double t = scale * _image->t(); // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, t / 2.0); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((s / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((s / 2.0), (t / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(t / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(s / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(s / 2.0), (t / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale ); if ( imageGeom ) { _geode->addDrawable( imageGeom ); } text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( (offset.x() + (s / 2.0) + 2), offset.y(), 0 ) ); } else { text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( 0, 0, 0 ) ); } if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getAttachPoint()->addChild( _geode ); // for clamping and occlusion culling //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl; applyStyle( _style ); setLightingIfNotSet( false ); ShaderGenerator gen; gen.setProgramName( "osgEarth.PlaceNode" ); gen.run( this, Registry::stateSetCache() ); // re-apply annotation drawable-level stuff as neccesary. AnnotationData* ad = getAnnotationData(); if ( ad ) setAnnotationData( ad ); if ( _dynamic ) setDynamic( _dynamic ); }
/** 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" ); } }
void Component::complete_path ( URI& path ) const { using namespace boost::algorithm; // CFinfo << "PATH [" << path.string() << "]\n" << CFflush; cf_assert( path.scheme() == URI::Scheme::CPATH ); if(path.empty()) path = "./"; if ( is_null(m_raw_parent) ) throw InvalidURI(FromHere(), "Component \'" + name() + "\' has no parent"); if (m_root.expired()) throw InvalidURI(FromHere(), "Component \'" + name() + "\' has no root"); boost::shared_ptr<Component> parent = m_raw_parent->self(); boost::shared_ptr<Component> root = m_root.lock(); std::string sp = path.path(); if ( path.is_relative() ) // transform it to absolute { if ( starts_with(sp,"/") ) // remove leading "/" if any boost::algorithm::replace_first(sp, "/", "" ); // substitute leading "../" for uri() of parent if (starts_with(sp,"..")) { std::string pfp = parent->uri().path(); boost::algorithm::replace_first(sp, "..", pfp); } // substitute leading "./" for uri() of this component else if (starts_with(sp,".")) { boost::algorithm::replace_first(sp, ".", uri().path()); } else { sp = uri().path()+"/"+sp; } } cf_assert ( URI(sp).is_absolute() ); // break path in tokens and loop on them, while concatenaitng to a new path boost::char_separator<char> sep("/"); typedef boost::tokenizer<boost::char_separator<char> > tokenizer; tokenizer tok (sp,sep); path = "/" ; std::string last; for(tokenizer::iterator el=tok.begin(); el!=tok.end(); ++el) { if ( equals (*el, ".") ) continue; // substitute any "/./" for nothing if ( equals (*el, "..") ) // substitute any "../" for base path path = path.base_path(); else path /= *el; } // CFinfo << "FINAL PATH: [" << path.string() << "]\n" << CFflush; cf_assert ( path.is_complete() ); }