예제 #1
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;
    }
예제 #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() );
    }
예제 #3
0
void CPlotter::set_data_set(const URI &uri)
{
  cf3_assert ( !uri.empty() );
  cf3_assert ( uri.scheme() == URI::Scheme::CPATH );

  m_data = uri;
}
예제 #4
0
void NLink::set_target_path(const URI & path)
{
  if(!path.empty())
  {
    Handle< CNode > target(access_component_checked(path));
    this->set_target_node(target);
  }
}
예제 #5
0
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();
}
예제 #6
0
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();
}
예제 #7
0
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);
}
예제 #8
0
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;
}
예제 #9
0
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;
	}
}
예제 #10
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;
    }
예제 #11
0
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 );
}
예제 #12
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" );
        }
    }
예제 #13
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;
}
예제 #14
0
파일: PlaceNode.cpp 프로젝트: 2php/osgearth
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();
}
예제 #15
0
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 );
}
예제 #16
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" );
        }
    }
예제 #17
0
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() );
}