コード例 #1
0
GeoImage
ElevationProxyImageLayer::createImage(const TileKey& key, ProgressCallback* progress)
{
    if ( _mapf.needsSync() )
    {
        Threading::ScopedMutexLock lock(_mapfMutex);
        if ( _mapf.needsSync() )
        {
            _mapf.sync();
        }
    }

    osg::ref_ptr<osg::HeightField> hf = HeightFieldUtils::createReferenceHeightField(key.getExtent(), 257,257, true );

    if ( _mapf.populateHeightField(hf, key, true, 0L) )
    {
        // encode the heightfield as a 16-bit normalized LUNIMANCE image
        osg::Image* image = new osg::Image();
        image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_LUMINANCE, GL_UNSIGNED_SHORT);
        image->setInternalTextureFormat( GL_LUMINANCE16 );
        const osg::FloatArray* floats = hf->getFloatArray();
        for( unsigned int i = 0; i < floats->size(); ++i  )
        {
            int col = i % hf->getNumColumns();
            int row = i / hf->getNumColumns();
            *(unsigned short*)image->data( col, row ) = (unsigned short)(32768 + (short)floats->at(i));
        }

        return GeoImage( image, key.getExtent() );
    }
    else
    {
        return GeoImage::INVALID;
    }
}
コード例 #2
0
ファイル: OSGTileFactory.cpp プロジェクト: hulumogu/osgearth
void
OSGTileFactory::addPlaceholderHeightfieldLayer(StreamingTile* tile,
                                               StreamingTile* ancestorTile,
                                               GeoLocator*    defaultLocator,
                                               const TileKey& key,
                                               const TileKey& ancestorKey)
{
    osgTerrain::HeightFieldLayer* newHFLayer = 0L;

    if ( ancestorTile && ancestorKey.valid() )
    {
        osg::ref_ptr<osgTerrain::HeightFieldLayer> ancestorLayer;
        {
            Threading::ScopedReadLock sharedLock( ancestorTile->getTileLayersMutex() );
            ancestorLayer = dynamic_cast<osgTerrain::HeightFieldLayer*>(ancestorTile->getElevationLayer());
        }

        if ( ancestorLayer.valid() )
        {
            osg::ref_ptr<osg::HeightField> ancestorHF = ancestorLayer->getHeightField();
            if ( ancestorHF.valid() )
            {
                osg::HeightField* newHF = HeightFieldUtils::createSubSample(
                    ancestorHF.get(),
                    ancestorKey.getExtent(),
                    key.getExtent());

                newHFLayer = new osgTerrain::HeightFieldLayer( newHF );
                newHFLayer->setLocator( defaultLocator );

                // lock to set the elevation layerdata:
                {
                    Threading::ScopedWriteLock exclusiveLock( tile->getTileLayersMutex() );
                    tile->setElevationLayer( newHFLayer );                
                    tile->setElevationLOD( ancestorTile->getElevationLOD() );
                }
            }
        }
    }

    // lock the tile to write the elevation data.
    {
        Threading::ScopedWriteLock exclusiveLock( tile->getTileLayersMutex() );

        if ( !newHFLayer )
        {
            newHFLayer = new osgTerrain::HeightFieldLayer();
            newHFLayer->setHeightField( createEmptyHeightField( key, 8, 8 ) );
            newHFLayer->setLocator( defaultLocator );
            tile->setElevationLOD( -1 );
        }

        if ( newHFLayer )
        {
            tile->setElevationLayer( newHFLayer );
        }
    }
}
コード例 #3
0
ファイル: Draggers.cpp プロジェクト: InterAtlas-ML/osgearth
void Dragger::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
{    
    GeoPoint p;
    _position.transform( key.getExtent().getSRS(), p );
    // first verify that the control position intersects the tile:
    if ( key.getExtent().contains( p.x(), p.y() ) )
    {
        updateTransform( tile );
    }
}
コード例 #4
0
ファイル: TMS.cpp プロジェクト: Arlockff/osgearth
bool
TileMap::intersectsKey(const TileKey& tilekey)
{
    osg::Vec3d keyMin, keyMax;

    //double keyMinX, keyMinY, keyMaxX, keyMaxY;

    //Check to see if the key overlaps the bounding box using lat/lon.  This is necessary to check even in 
    //Mercator situations in case the BoundingBox is described using lat/lon coordinates such as those produced by GDAL2Tiles
    //This should be considered a bug on the TMS production side, but we can work around it for now...
    tilekey.getExtent().getBounds(keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y());
    //tilekey.getExtent().getBounds(keyMinX, keyMinY, keyMaxX, keyMaxY);

    bool inter = intersects(_minX, _minY, _maxX, _maxY, keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y() ); //keyMinX, keyMinY, keyMaxX, keyMaxY);

    if (!inter && tilekey.getProfile()->getSRS()->isSphericalMercator())
    {
        tilekey.getProfile()->getSRS()->transform(keyMin, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMin );
        tilekey.getProfile()->getSRS()->transform(keyMax, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMax );
        inter = intersects(_minX, _minY, _maxX, _maxY, keyMin.x(), keyMin.y(), keyMax.x(), keyMax.y() );
        //tilekey.getProfile()->getSRS()->transform2D(keyMinX, keyMinY, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMinX, keyMinY);
        //tilekey.getProfile()->getSRS()->transform2D(keyMaxX, keyMaxY, tilekey.getProfile()->getSRS()->getGeographicSRS(), keyMaxX, keyMaxY);
        //inter = intersects(_minX, _minY, _maxX, _maxY, keyMinX, keyMinY, keyMaxX, keyMaxY);
    }

    return inter;
}
コード例 #5
0
GeoImage
ElevationProxyImageLayer::createImage(const TileKey& key, ProgressCallback* progress, bool forceFallback)
{
    osg::ref_ptr<Map> map = _sourceMap.get();
    if ( map.valid() )
    {
        osg::ref_ptr<osg::HeightField> hf;
        if ( map->getHeightField( key, true, hf ) )
        {
            // encode the heightfield as a 16-bit normalized LUNIMANCE image
            osg::Image* image = new osg::Image();
            image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_LUMINANCE, GL_UNSIGNED_SHORT);
            image->setInternalTextureFormat( GL_LUMINANCE16 );
            const osg::FloatArray* floats = hf->getFloatArray();
            for( unsigned int i = 0; i < floats->size(); ++i  )
            {
                int col = i % hf->getNumColumns();
                int row = i / hf->getNumColumns();
                *(unsigned short*)image->data( col, row ) = (unsigned short)(32768 + (short)floats->at(i));
            }

            return GeoImage( image, key.getExtent() );
        }
    }
    return GeoImage::INVALID;
}
コード例 #6
0
SurfaceNode::SurfaceNode(const TileKey&        tilekey,
                         const MapInfo&        mapinfo,
                         const RenderBindings& bindings,
                         TileDrawable*         drawable)
{
    _tileKey = tilekey;

    _drawable = drawable;

    _surfaceGeode = new osg::Geode();
    _surfaceGeode->addDrawable( drawable );

    // Create the final node.
    addChild( _surfaceGeode.get() );

    // Establish a local reference frame for the tile:
    GeoPoint centroid;
    tilekey.getExtent().getCentroid(centroid);

    osg::Matrix local2world;
    centroid.createLocalToWorld( local2world );
    setMatrix( local2world );

    _matrix = new osg::RefMatrix( local2world );

    // Initialize the cached bounding box.
    setElevationRaster( 0L, osg::Matrixf::identity() );
}
コード例 #7
0
void
LocalGeometryNode::onTileAdded(const TileKey&          key, 
                               osg::Node*              graph, 
                               TerrainCallbackContext& context)
{
    bool needsClamp;

    // This was faster, but less precise and resulted in a lot of unnecessary clamp attempts:
    //if ( _boundingPT.contains(patch->getBound()) )

    // Does the tile key's polytope intersect the world bounds or this object?
    // (taking getParent(0) gives the world-tranformed bounds vs. local bounds)
    if (key.valid())
    {
        osg::Polytope tope;
        key.getExtent().createPolytope(tope);
        needsClamp = tope.contains(this->getParent(0)->getBound());
    }
    else
    {
        // with no key, must clamp no matter what
        needsClamp = true;
    }

    if (needsClamp)
    {    
        clamp(graph, context.getTerrain());
    }
}
コード例 #8
0
SurfaceNode::SurfaceNode(const TileKey&        tilekey,
                         const MapInfo&        mapinfo,
                         const RenderBindings& bindings,
                         TileDrawable*         drawable)
: _debugNodeVisible(false)
{
    _tileKey = tilekey;

    _drawable = drawable;

    _surfaceGeode = new osg::Geode();
    _surfaceGeode->addDrawable( drawable );
    
    // Create the final node.
    addChild( _surfaceGeode.get() );
        
    // Establish a local reference frame for the tile:
    osg::Vec3d centerWorld;
    GeoPoint centroid;
    tilekey.getExtent().getCentroid(centroid);
    centroid.toWorld(centerWorld);
    osg::Matrix local2world;
    centroid.createLocalToWorld( local2world );
    setMatrix( local2world );

    _worldCorners.resize(8);
    _childrenCorners.resize(4);
    for(size_t i = 0; i < _childrenCorners.size(); ++i)
    {
        _childrenCorners[i].resize(8);
    }
    // Initialize the cached bounding box.
    setElevationExtrema(osg::Vec2f(0, 0));
}
コード例 #9
0
ファイル: FeatureNode.cpp プロジェクト: pprabhu78/osgearth
// This will be called by AnnotationNode when a new terrain tile comes in.
void
FeatureNode::onTileAdded(const TileKey&          key,
                         osg::Node*              graph,
                         TerrainCallbackContext& context)
{
    if (!_clampDirty)
    {
        bool needsClamp;

        if (key.valid())
        {
            osg::Polytope tope;
            key.getExtent().createPolytope(tope);
            needsClamp = tope.contains(this->getBound());
        }
        else
        {
            // without a valid tilekey we don't know the extent of the change,
            // so clamping is required.
            needsClamp = true;
        }

        if (needsClamp)
        {
            _clampDirty = true;
            ADJUST_UPDATE_TRAV_COUNT(this, +1);
            //clamp(graph, context.getTerrain());
        }
    }
}
コード例 #10
0
ファイル: SimplePager.cpp プロジェクト: 469447793/osgearth
osg::BoundingSphere SimplePager::getBounds(const TileKey& key) const
{
    int samples = 6;

    GeoExtent extent = key.getExtent();

    double xSample = extent.width() / (double)samples;
    double ySample = extent.height() / (double)samples;

    osg::BoundingSphere bs;
    for (int c = 0; c < samples+1; c++)
    {
        double x = extent.xMin() + (double)c * xSample;
        for (int r = 0; r < samples+1; r++)
        {
            double y = extent.yMin() + (double)r * ySample;
            osg::Vec3d world;

            GeoPoint samplePoint(extent.getSRS(), x, y, 0, ALTMODE_ABSOLUTE);

            GeoPoint wgs84 = samplePoint.transform(osgEarth::SpatialReference::create("epsg:4326"));
            wgs84.toWorld(world);
            bs.expandBy(world);
        }
    }
    return bs;
}
コード例 #11
0
ファイル: ImageLayer.cpp プロジェクト: caishanli/osgearth
GeoImage
ImageLayer::createImageFromTileSource(const TileKey&    key,
                                      ProgressCallback* progress)
{
    TileSource* source = getTileSource();
    if ( !source )
        return GeoImage::INVALID;

    // If the profiles are different, use a compositing method to assemble the tile.
    if ( !key.getProfile()->isHorizEquivalentTo( getProfile() ) )
    {
        return assembleImage( key, progress );
    }

    // Good to go, ask the tile source for an image:
    osg::ref_ptr<TileSource::ImageOperation> op = getOrCreatePreCacheOp();

    // Fail is the image is blacklisted.
    if ( source->getBlacklist()->contains(key) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: blacklisted(" << key.str() << ")" << std::endl;
        return GeoImage::INVALID;
    }

    if (!mayHaveData(key))
    {
        OE_DEBUG << LC << "createImageFromTileSource: mayHaveData(" << key.str() << ") == false" << std::endl;
        return GeoImage::INVALID;
    }

    //if ( !source->hasData( key ) )
    //{
    //    OE_DEBUG << LC << "createImageFromTileSource: hasData(" << key.str() << ") == false" << std::endl;
    //    return GeoImage::INVALID;
    //}

    // create an image from the tile source.
    osg::ref_ptr<osg::Image> result = source->createImage( key, op.get(), progress );   

    // Process images with full alpha to properly support MP blending.    
    if (result.valid() && 
        options().featherPixels() == true)
    {
        ImageUtils::featherAlphaRegions( result.get() );
    }    
    
    // If image creation failed (but was not intentionally canceled and 
    // didn't time out or end for any other recoverable reason), then
    // blacklist this tile for future requests.
    if (result == 0L)
    {
        if ( progress == 0L ||
             ( !progress->isCanceled() && !progress->needsRetry() ) )
        {
            source->getBlacklist()->add( key );
        }
    }

    return GeoImage(result.get(), key.getExtent());
}
コード例 #12
0
ファイル: OrthoNode.cpp プロジェクト: ender35/osgearth
void
OrthoNode::reclamp( const TileKey& key, osg::Node* tile, const Terrain* terrain )
{
    // first verify that the label position intersects the tile:
    if ( key.getExtent().contains( _mapPosition.x(), _mapPosition.y() ) )
    {
        updateTransforms( _mapPosition, tile );
    }
}
コード例 #13
0
static void applyBlast(GeoPoint& center, double radius, double offset, const TileKey& key, osg::HeightField* heightField)
{
    //Get the extents of the tile
    double xmin, ymin, xmax, ymax;
    key.getExtent().getBounds(xmin, ymin, xmax, ymax);

    int tileSize = heightField->getNumColumns();

    // Iterate over the output heightfield and sample the data that was read into it.
    double dx = (xmax - xmin) / (tileSize-1);
    double dy = (ymax - ymin) / (tileSize-1);     

    const SpatialReference* srs = SpatialReference::create("wgs84");

    for (int c = 0; c < tileSize; ++c)
    {
        double geoX = xmin + (dx * (double)c);
        for (int r = 0; r < tileSize; ++r)
        {
            double geoY = ymin + (dy * (double)r);

            GeoPoint geo(srs, geoX, geoY, center.z(), ALTMODE_ABSOLUTE);

            double distance = geo.distanceTo( center );
            double ratio = distance / radius;
            if (ratio <= 1.0)
            {
                double weight = 1.0 - osg::clampBetween(ratio, 0.0, 1.0);
                if (weight > 0)
                {
                    float h = center.z() + offset * weight;
                    heightField->setHeight(c, r, h);
                }
            }
            
            /*


            if ( boundary->contains2D(geo.x(), geo.y()) )
            {
                float h = heightField->getHeight( c, r );
                if (h == NO_DATA_VALUE)
                {
                    //h = deformation._offset;
                }
                else
                {
                    //h += deformation._offset;                    
                    h = deformation._offset;
                }
                heightField->setHeight(c, r, h);
            } 
            */
        }
    }
}
コード例 #14
0
ファイル: GeometryPool.cpp プロジェクト: rhabacker/osgearth
void
GeometryPool::createKeyForTileKey(const TileKey&             tileKey,
                                  unsigned                   size,
                                  const MapInfo&             mapInfo,
                                  GeometryPool::GeometryKey& out) const
{
    out.lod  = tileKey.getLOD();
    out.yMin = mapInfo.isGeocentric()? tileKey.getExtent().yMin() : 0.0;
    out.size = size;
}
コード例 #15
0
osg::Node*
RexTerrainEngineNode::createTile( const TileKey& key )
{
     // Compute the sample size to use for the key's level of detail that will line up exactly with the tile size of the highest level of subdivision of the rex engine.
    unsigned int sampleSize = computeSampleSize( key.getLevelOfDetail() );    
    OE_INFO << LC << "Computed a sample size of " << sampleSize << " for lod " << key.getLevelOfDetail() << std::endl;

    TileKey sampleKey = key;

    // ALWAYS use 257x257 b/c that is what rex always uses.
    osg::ref_ptr< osg::HeightField > out_hf = HeightFieldUtils::createReferenceHeightField(
            key.getExtent(), 257, 257, 0u, true );

    sampleKey = key;

    bool populated = false;
    while (!populated)
    {
        populated = _update_mapf->populateHeightField(
            out_hf,
            sampleKey,
            true, // convertToHAE
            0 );

        if (!populated)
        {
            // Fallback on the parent
            sampleKey = sampleKey.createParentKey();
            if (!sampleKey.valid())
            {
                return 0;
            }
        }
    }

    // cannot happen (says coverity; see loop above), so commenting this out -gw
#if 0
    if (!populated)
    {
        // We have no heightfield so just create a reference heightfield.
        out_hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 257, 257, 0u);
        sampleKey = key;
    }
#endif

    GeoHeightField geoHF( out_hf.get(), sampleKey.getExtent() );    
    if (sampleKey != key)
    {   
        geoHF = geoHF.createSubSample( key.getExtent(), sampleSize, sampleSize, osgEarth::INTERP_BILINEAR);         
    }

    // We should now have a heightfield that matches up exactly with the requested key at the appropriate resolution.
    // Turn it into triangles.
    return renderHeightField( geoHF );      
}
コード例 #16
0
ファイル: TerrainLayer.cpp プロジェクト: caishanli/osgearth
bool
TerrainLayer::isKeyInLegalRange(const TileKey& key) const
{    
    if ( !key.valid() )
    {
        return false;
    }

    // We must use the equivalent lod b/c the input key can be in any profile.
    unsigned localLOD = getProfile() ?
        getProfile()->getEquivalentLOD(key.getProfile(), key.getLOD()) :
        key.getLOD();


    // First check the key against the min/max level limits, it they are set.
    if ((options().maxLevel().isSet() && localLOD > options().maxLevel().value()) ||
        (options().minLevel().isSet() && localLOD < options().minLevel().value()))
    {
        return false;
    }

    // Next check the maxDataLevel if that is set.
    if (options().maxDataLevel().isSet() && localLOD > options().maxDataLevel().get())
    {
        return false;
    }

    // Next, check against resolution limits (based on the source tile size).
    if (options().minResolution().isSet() || options().maxResolution().isSet())
    {
        const Profile* profile = getProfile();
        if ( profile )
        {
            // calculate the resolution in the layer's profile, which can
            // be different that the key's profile.
            double resKey   = key.getExtent().width() / (double)getTileSize();
            double resLayer = key.getProfile()->getSRS()->transformUnits(resKey, profile->getSRS());

            if (options().maxResolution().isSet() &&
                options().maxResolution().value() > resLayer)
            {
                return false;
            }

            if (options().minResolution().isSet() &&
                options().minResolution().value() < resLayer)
            {
                return false;
            }
        }
    }

	return true;
}
コード例 #17
0
ファイル: ElevationPool.cpp プロジェクト: filnet/osgearth
bool
ElevationPool::fetchTileFromMap(const TileKey& key, MapFrame& frame, Tile* tile)
{
    tile->_loadTime = osg::Timer::instance()->tick();

    osg::ref_ptr<osg::HeightField> hf = new osg::HeightField();
    hf->allocate( _tileSize, _tileSize );

    // Initialize the heightfield to nodata
    hf->getFloatArray()->assign( hf->getFloatArray()->size(), NO_DATA_VALUE );

    TileKey keyToUse = key;
    while( !tile->_hf.valid() && keyToUse.valid() )
    {
        bool ok;
        if (_layers.empty())
        {
            OE_TEST << LC << "Populating from FULL MAP (" << keyToUse.str() << ")\n";
            ok = frame.populateHeightField(hf, keyToUse, false /*heightsAsHAE*/, 0L);
        }
        else
        {
            OE_TEST << LC << "Populating from layers (" << keyToUse.str() << ")\n";
            ok = _layers.populateHeightFieldAndNormalMap(hf.get(), 0L, keyToUse, 0L, INTERP_BILINEAR, 0L);
        }

        if (ok)
        {
            tile->_hf = GeoHeightField( hf.get(), keyToUse.getExtent() );
            tile->_bounds = keyToUse.getExtent().bounds();
        }
        else
        {
            keyToUse = keyToUse.createParentKey();
        }
    }

    return tile->_hf.valid();
}
コード例 #18
0
ファイル: ImageLayer.cpp プロジェクト: aashish24/osgearth
GeoImage
ImageLayer::createImageFromTileSource(const TileKey&    key,
                                      ProgressCallback* progress)
{
    TileSource* source = getTileSource();
    if ( !source )
        return GeoImage::INVALID;

    // If the profiles are different, use a compositing method to assemble the tile.
    if ( !key.getProfile()->isHorizEquivalentTo( getProfile() ) )
    {
        return assembleImageFromTileSource( key, progress );
    }

    // Good to go, ask the tile source for an image:
    osg::ref_ptr<TileSource::ImageOperation> op = _preCacheOp;

    // Fail is the image is blacklisted.
    if ( source->getBlacklist()->contains(key) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: blacklisted(" << key.str() << ")" << std::endl;
        return GeoImage::INVALID;
    }
    
    if ( !source->hasData( key ) )
    {
        OE_DEBUG << LC << "createImageFromTileSource: hasData(" << key.str() << ") == false" << std::endl;
        return GeoImage::INVALID;
    }

    // create an image from the tile source.
    osg::ref_ptr<osg::Image> result = source->createImage( key, op.get(), progress );

    // Process images with full alpha to properly support MP blending.    
    if ( result.valid() && *_runtimeOptions.featherPixels())
    {
        ImageUtils::featherAlphaRegions( result.get() );
    }    
    
    // If image creation failed (but was not intentionally canceled),
    // blacklist this tile for future requests.
    if ( result == 0L && (!progress || !progress->isCanceled()) )
    {
        source->getBlacklist()->add( key );
    }

    return GeoImage(result.get(), key.getExtent());
}
コード例 #19
0
ファイル: Profile.cpp プロジェクト: Sylla/osgearth
void
Profile::getIntersectingTiles(const TileKey& key, std::vector<TileKey>& out_intersectingKeys) const
{
    OE_DEBUG << "GET ISECTING TILES for key " << key.str() << " -----------------" << std::endl;

    //If the profiles are exactly equal, just add the given tile key.
    if ( isEquivalentTo( key.getProfile() ) )
    {
        //Clear the incoming list
        out_intersectingKeys.clear();

        out_intersectingKeys.push_back(key);
        return;
    }
    return getIntersectingTiles(key.getExtent(), out_intersectingKeys);
}
コード例 #20
0
    std::string createURI( const TileKey& key ) const
    {
        double minx, miny, maxx, maxy;
        key.getExtent().getBounds( minx, miny, maxx, maxy);
        
        char buf[2048];
        sprintf(buf, _prototype.c_str(), minx, miny, maxx, maxy);
        
        std::string uri(buf);

        // url-ize the uri before returning it
        if ( osgDB::containsServerAddress( uri ) )
            uri = replaceIn(uri, " ", "%20");

        return uri;
    }
コード例 #21
0
ファイル: TileVisitor.cpp プロジェクト: energonQuest/dtEarth
void TileVisitor::processKey( const TileKey& key )
{        
    // If we've been cancelled then just return.
    if (_progress && _progress->isCanceled())
    {        
        return;
    }    

    unsigned int x, y, lod;
    key.getTileXY(x, y);
    lod = key.getLevelOfDetail();    

    // Only process this key if it has a chance of succeeding.
    if (_tileHandler && !_tileHandler->hasData(key))
    {                
        return;
    }    

    bool traverseChildren = false;

    // If the key intersects the extent attempt to traverse
    if (intersects( key.getExtent() ))
    {
        // If the lod is less than the min level don't do anything but do traverse the children.
        if (lod < _minLevel)
        {
            traverseChildren = true;
        }
        else
        {         
            // Process the key
            traverseChildren = handleTile( key );        
        }
    }

    // Traverse the children
    if (traverseChildren && lod < _maxLevel)
    {
        for (unsigned int i = 0; i < 4; i++)
        {
            TileKey k = key.createChildKey(i);
            processKey( k );
        }                                
    }       
}
コード例 #22
0
bool
TerrainLayer::isKeyInRange(const TileKey& key) const
{    
    if ( !key.valid() )
    {
        return false;
    }

    // First check the key against the min/max level limits, it they are set.
    if ((_runtimeOptions->maxLevel().isSet() && key.getLOD() > _runtimeOptions->maxLevel().value()) ||
        (_runtimeOptions->minLevel().isSet() && key.getLOD() < _runtimeOptions->minLevel().value()))
    {
        return false;
    }

    // Next, check against resolution limits (based on the source tile size).
    if (_runtimeOptions->minResolution().isSet() ||
        _runtimeOptions->maxResolution().isSet())
    {
        const Profile* profile = getProfile();
        if ( profile )
        {
            // calculate the resolution in the layer's profile, which can
            // be different that the key's profile.
            double resKey   = key.getExtent().width() / (double)getTileSize();
            double resLayer = key.getProfile()->getSRS()->transformUnits(resKey, profile->getSRS());

            if (_runtimeOptions->maxResolution().isSet() &&
                _runtimeOptions->maxResolution().value() > resLayer)
            {
                return false;
            }

            if (_runtimeOptions->minResolution().isSet() &&
                _runtimeOptions->minResolution().value() < resLayer)
            {
                return false;
            }
        }
    }

	return true;
}
コード例 #23
0
ファイル: GeoTransform.cpp プロジェクト: 469447793/osgearth
void
GeoTransform::onTileAdded(const TileKey&          key,
                          osg::Node*              node,
                          TerrainCallbackContext& context)
{
   if (!_position.isValid() || _position.altitudeMode() != ALTMODE_RELATIVE)
   {
       OE_TEST << LC << "onTileAdded fail condition 1\n";
       return;
   }

   if (!key.getExtent().contains(_position))
   {
       OE_DEBUG << LC << "onTileAdded fail condition 2\n";
       return;
   }

   setPosition(_position);
}
コード例 #24
0
ファイル: TerrainLayer.cpp プロジェクト: czz2012/osgearth
bool
TerrainLayer::isKeyValid(const TileKey& key) const
{    
    if (!key.valid())
        return false;

    // Check to see if an explicity max LOD is set. Do NOT compare against the minLevel,
    // because we still need to create empty tiles until we get to the data. The ImageLayer
    // will deal with this.
    if ( _runtimeOptions->maxLevel().isSet() && key.getLOD() > _runtimeOptions->maxLevel().value() ) 
    {
        return false;
    }

    // Check to see if levels of detail based on resolution are set
    const Profile* profile = getProfile();
    if ( profile )
    {
        if ( !profile->isEquivalentTo( key.getProfile() ) )
        {
            OE_DEBUG << LC
                << "TerrainLayer::isKeyValid called with key of a different profile" << std::endl;
            //return true;
        }

        if ( _runtimeOptions->maxResolution().isSet() )
        {
            double keyres = key.getExtent().width() / (double)getTileSize();
            double keyresInLayerProfile = key.getProfile()->getSRS()->transformUnits(keyres, profile->getSRS());

            if ( _runtimeOptions->maxResolution().isSet() && keyresInLayerProfile < _runtimeOptions->maxResolution().value() )
            {
                return false;
            }
        }
    }

	return true;
}
コード例 #25
0
ファイル: WCS10Source.cpp プロジェクト: ifad-ts/osgearth
osgEarth::HTTPRequest WCS10Source::createRequest(const TileKey& key) const
{
    std::stringstream buf;

    double lon_min, lat_min, lon_max, lat_max;
    key.getExtent().getBounds(lon_min, lat_min, lon_max, lat_max);

    int lon_samples = _options.tileSize().value();
    int lat_samples = _options.tileSize().value();
    double lon_interval = (lon_max - lon_min) / (double)(lon_samples - 1);
    double lat_interval = (lat_max - lat_min) / (double)(lat_samples - 1);

    HTTPRequest req(_options.url()->full());

    req.addParameter("SERVICE", "WCS");
    req.addParameter("VERSION", "1.0.0");
    req.addParameter("REQUEST", "GetCoverage");
    req.addParameter("COVERAGE", _options.identifier().value());
    req.addParameter("FORMAT", _covFormat);

    req.addParameter("CRS", "urn:ogc:def:crs:EPSG::4326");

    buf.str("");
    buf << lon_min << "," << lat_min << "," << lon_max << "," << lat_max;
    req.addParameter("BBOX", buf.str());

    buf.str("");
    buf << lon_samples;
    req.addParameter("WIDTH", buf.str());
    buf.str("");
    buf << lat_samples;
    req.addParameter("HEIGHT", buf.str());

    // Not supported in WCS 1.0.0...
    //if (!_options.rangeSubset()->empty())
    //    req.addParameter("RangeSubset", _options.rangeSubset().value());

    return req;
}
コード例 #26
0
ファイル: Profile.cpp プロジェクト: ldelgass/osgearth
void
Profile::getIntersectingTiles(const TileKey& key, std::vector<TileKey>& out_intersectingKeys) const
{
    OE_DEBUG << "GET ISECTING TILES for key " << key.str() << " -----------------" << std::endl;

    //If the profiles are exactly equal, just add the given tile key.
    if ( isHorizEquivalentTo( key.getProfile() ) )
    {
        //Clear the incoming list
        out_intersectingKeys.clear();
        out_intersectingKeys.push_back(key);
    }
    else
    {
        // figure out which LOD in the local profile is a best match for the LOD
        // in the source LOD in terms of resolution.
        unsigned localLOD = getEquivalentLOD(key.getProfile(), key.getLOD());
        getIntersectingTiles(key.getExtent(), localLOD, out_intersectingKeys);

        OE_DEBUG << LC << "GIT, key="<< key.str() << ", localLOD=" << localLOD
            << ", resulted in " << out_intersectingKeys.size() << " tiles" << std::endl;
    }
}
コード例 #27
0
/**
* Applies the deformation to the heightfield with the given key.
*/
static void deformHeightField(const Deformation& deformation, const TileKey& key, osg::HeightField* heightField)
{   
    osgEarth::Symbology::Polygon* boundary = dynamic_cast<osgEarth::Symbology::Polygon*>(deformation._feature->getGeometry());
    if (!boundary)
    {
        OE_WARN << "NOT A POLYGON" << std::endl;
        return;
    }

    //Get the extents of the tile
    double xmin, ymin, xmax, ymax;
    key.getExtent().getBounds(xmin, ymin, xmax, ymax);

    int tileSize = heightField->getNumColumns();

    // Iterate over the output heightfield and sample the data that was read into it.
    double dx = (xmax - xmin) / (tileSize-1);
    double dy = (ymax - ymin) / (tileSize-1);     


    const SpatialReference* srs = SpatialReference::create("wgs84");

    for (int c = 0; c < tileSize; ++c)
    {
        double geoX = xmin + (dx * (double)c);
        for (int r = 0; r < tileSize; ++r)
        {
            double geoY = ymin + (dy * (double)r);

            GeoPoint geo(srs, geoX, geoY, 0.0, ALTMODE_ABSOLUTE);
            if ( boundary->contains2D(geo.x(), geo.y()) )
            {
                heightField->setHeight(c, r, deformation._offset);
            }                
        }
    }
}
コード例 #28
0
 bool intersects(const TileKey& key)
 {
     return key.getExtent().intersects( _extents );
 }
コード例 #29
0
osg::Image*
CompositeTileSource::createImage(const TileKey&    key,
                                 ProgressCallback* progress )
{
    ImageMixVector images;
    images.reserve( _options._components.size() );

    for(CompositeTileSourceOptions::ComponentVector::const_iterator i = _options._components.begin();
        i != _options._components.end();
        ++i )
    {
        if ( progress && progress->isCanceled() )
            return 0L;

        ImageInfo imageInfo;
        imageInfo.dataInExtents = false;



        TileSource* source = i->_tileSourceInstance.get();
        if ( source )
        {
            //TODO:  This duplicates code in ImageLayer::isKeyValid.  Maybe should move that to TileSource::isKeyValid instead
            int minLevel = 0;
            int maxLevel = INT_MAX;
            if (i->_imageLayerOptions->minLevel().isSet())
            {
                minLevel = i->_imageLayerOptions->minLevel().value();
            }
            else if (i->_imageLayerOptions->minResolution().isSet())
            {
                minLevel = source->getProfile()->getLevelOfDetailForHorizResolution( 
                    i->_imageLayerOptions->minResolution().value(), 
                    source->getPixelsPerTile());
            }

            if (i->_imageLayerOptions->maxLevel().isSet())
            {
                maxLevel = i->_imageLayerOptions->maxLevel().value();
            }
            else if (i->_imageLayerOptions->maxResolution().isSet())
            {
                maxLevel = source->getProfile()->getLevelOfDetailForHorizResolution( 
                    i->_imageLayerOptions->maxResolution().value(), 
                    source->getPixelsPerTile());
            }

            // check that this source is within the level bounds:
            if (minLevel > (int)key.getLevelOfDetail() ||
                maxLevel < (int)key.getLevelOfDetail() )
            {
                continue;
            }
            
                //Only try to get data if the source actually has data                
                if (source->hasDataInExtent( key.getExtent() ) )
                {
                    //We have data within these extents
                    imageInfo.dataInExtents = true;

                    if ( !source->getBlacklist()->contains( key.getTileId() ) )
                    {                        
                        osg::ref_ptr< ImageLayerPreCacheOperation > preCacheOp;
                        if ( i->_imageLayerOptions.isSet() )
                        {
                            preCacheOp = new ImageLayerPreCacheOperation();
                            preCacheOp->_processor.init( i->_imageLayerOptions.value(), _dbOptions.get(), true );                        
                        }

                        imageInfo.image = source->createImage( key, preCacheOp.get(), progress );
                        imageInfo.opacity = 1.0f;

                        //If the image is not valid and the progress was not cancelled, blacklist
                        if (!imageInfo.image.valid() && (!progress || !progress->isCanceled()))
                        {
                            //Add the tile to the blacklist
                            OE_DEBUG << LC << "Adding tile " << key.str() << " to the blacklist" << std::endl;
                            source->getBlacklist()->add( key.getTileId() );
                        }
                        imageInfo.opacity = i->_imageLayerOptions.isSet() ? i->_imageLayerOptions->opacity().value() : 1.0f;
                    }
                }
                else
                {
                    OE_DEBUG << LC << "Source has no data at " << key.str() << std::endl;
                }
        }

        //Add the ImageInfo to the list
        images.push_back( imageInfo );
    }

    unsigned numValidImages = 0;
    osg::Vec2s textureSize;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid())
        {
            if (numValidImages == 0)
            {
                textureSize.set( info.image->s(), info.image->t());
            }
            numValidImages++;        
        }
    }

    //Try to fallback on any empty images if we have some valid images but not valid images for ALL layers
    if (numValidImages > 0 && numValidImages < images.size())
    {        
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            if (!info.image.valid() && info.dataInExtents)
            {                                
                TileKey parentKey = key.createParentKey();

                TileSource* source = _options._components[i]._tileSourceInstance;
                if (source)
                {                 
                    osg::ref_ptr< ImageLayerPreCacheOperation > preCacheOp;
                    if ( _options._components[i]._imageLayerOptions.isSet() )
                    {
                        preCacheOp = new ImageLayerPreCacheOperation();
                        preCacheOp->_processor.init( _options._components[i]._imageLayerOptions.value(), _dbOptions.get(), true );                        
                    }                

                    osg::ref_ptr< osg::Image > image;
                    while (!image.valid() && parentKey.valid())
                    {                        
                        image = source->createImage( parentKey, preCacheOp.get(), progress );
                        if (image.valid())
                        {                     
                            break;
                        }
                        parentKey = parentKey.createParentKey();
                    }     

                    if (image.valid())
                    {
                        //We got an image, but now we need to crop it to match the incoming key's extents
                        GeoImage geoImage( image.get(), parentKey.getExtent());
                        GeoImage cropped = geoImage.crop( key.getExtent(), true, textureSize.x(), textureSize.y(), *source->_options.bilinearReprojection());
                        image = cropped.getImage();
                    }

                    info.image = image.get();
                }
            }
        }
    }

    //Recompute the number of valid images
    numValidImages = 0;
    for (unsigned int i = 0; i < images.size(); i++)
    {
        ImageInfo& info = images[i];
        if (info.image.valid()) numValidImages++;        
    }

    if ( progress && progress->isCanceled() )
    {
        return 0L;
    }
    else if ( numValidImages == 0 )
    {
        return 0L;
    }
    else if ( numValidImages == 1 )
    {
        //We only have one valid image, so just return it and don't bother with compositing
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& info = images[i];
            if (info.image.valid())
                return info.image.release();
        }
        return 0L;
    }
    else
    {
        osg::Image* result = 0;
        for (unsigned int i = 0; i < images.size(); i++)
        {
            ImageInfo& imageInfo = images[i];
            if (!result)
            {
                if (imageInfo.image.valid())
                {
                    result = new osg::Image( *imageInfo.image.get());
                }
            }
            else
            {
                if (imageInfo.image.valid())
                {
                    ImageUtils::mix( result, imageInfo.image, imageInfo.opacity );
                }
            }            
        }        
        return result;
    }
}
コード例 #30
0
void
TileModelFactory::createTileModel(const TileKey&           key, 
                                  const MapFrame&          frame,
                                  bool                     accumulate,
                                  osg::ref_ptr<TileModel>& out_model,
                                  ProgressCallback*        progress)
{

    osg::ref_ptr<TileModel> model = new TileModel( frame.getRevision(), frame.getMapInfo() );

    model->_useParentData = _terrainReqs->parentTexturesRequired();

    model->_tileKey = key;
    model->_tileLocator = GeoLocator::createForKey(key, frame.getMapInfo());

    OE_START_TIMER(fetch_imagery);

    // Fetch the image data and make color layers.
    unsigned index = 0;
    unsigned order = 0;
    for( ImageLayerVector::const_iterator i = frame.imageLayers().begin(); i != frame.imageLayers().end(); ++i )
    {
        ImageLayer* layer = i->get();

        if ( layer->getEnabled() && layer->isKeyInRange(key) )
        {
            BuildColorData build;
            build.init( key, layer, order, frame.getMapInfo(), _terrainOptions, _liveTiles.get(), model.get() );

            bool addedToModel = build.execute(progress);
            if ( addedToModel )
            {
                // only bump the order if we added something to the data model.
                order++;
            }
        }
    }

    if (progress)
        progress->stats()["fetch_imagery_time"] += OE_STOP_TIMER(fetch_imagery);

    
    // make an elevation layer.
    OE_START_TIMER(fetch_elevation);
    buildElevation(key, frame, accumulate, _terrainReqs->elevationTexturesRequired(), model.get(), progress);
    if (progress)
        progress->stats()["fetch_elevation_time"] += OE_STOP_TIMER(fetch_elevation);
    
    // make a normal map layer (if necessary)
    if ( _terrainReqs->normalTexturesRequired() )
    {
        OE_START_TIMER(fetch_normalmap);
        buildNormalMap(key, frame, accumulate, model.get(), progress);
        if (progress)
            progress->stats()["fetch_normalmap_time"] += OE_STOP_TIMER(fetch_normalmap);
    }

    // If nothing was added, not even a fallback heightfield, something went
    // horribly wrong. Leave without a tile model. Chances are that a parent tile
    // not not found in the live-tile registry.
    if ( model->_colorData.size() == 0 && !model->_elevationData.getHeightField() )
    {
        return;
    }

    // OK we are making a tile, so if there's no heightfield yet, make an empty one (and mark it
    // as fallback data of course)
    if ( !model->_elevationData.getHeightField() )
    {
        osg::HeightField* hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 15, 15 );
        model->_elevationData = TileModel::ElevationData(
            hf,
            GeoLocator::createForKey(key, frame.getMapInfo()),
            true );
    }

    // look up the parent model and cache it.
    osg::ref_ptr<TileNode> parentTile;
    if ( _liveTiles->get(key.createParentKey(), parentTile) )
    {
        model->_parentModel = parentTile->getTileModel();
    }

    out_model = model.release();
}