Esempio n. 1
0
bool
TileSource::hasData(const osgEarth::TileKey& key) const
{
    //sematics: "might have data"

    if ( !key.valid() )
        return false;

    // If no data extents are provided, and there's no data level override,
    // return true because there might be data but there's no way to tell.
    if (_dataExtents.size() == 0 && !_options.maxDataLevel().isSet())
    {
        return true;
    }

    unsigned int lod = key.getLevelOfDetail();

    // Remap the lod to an appropriate lod if it's not in the same SRS        
    if (!key.getProfile()->isHorizEquivalentTo( getProfile() ) )
    {        
        lod = getProfile()->getEquivalentLOD( key.getProfile(), key.getLevelOfDetail() );        
    }

    // If there's an explicit LOD override and we've exceeded it, no data.
    if (_options.maxDataLevel().isSet() && lod > _options.maxDataLevel().value())
    {
        return false;
    }

    // If there are no extents to check, there might be data.
    if (_dataExtents.size() == 0)
    {
        return true;
    }

    bool intersectsData = false;
    const osgEarth::GeoExtent& keyExtent = key.getExtent();
    
    for (DataExtentList::const_iterator itr = _dataExtents.begin(); itr != _dataExtents.end(); ++itr)
    {
        if ((keyExtent.intersects( *itr )) && 
            (!itr->minLevel().isSet() || itr->minLevel() <= lod ) &&
            (!itr->maxLevel().isSet() || itr->maxLevel() >= lod ))
        {
            intersectsData = true;
            break;
        }
    }

    return intersectsData;
}
Esempio n. 2
0
std::string
DiskCache::getFilename(const osgEarth::TileKey& key, const CacheSpec& spec ) const
{
	unsigned int level, x, y;
    level = key.getLevelOfDetail() +1;
    key.getTileXY( x, y );

    unsigned int numCols, numRows;
    key.getProfile()->getNumTiles(level, numCols, numRows);

    // need to invert the y-tile index
    y = numRows - y - 1;

    char buf[2048];
    sprintf( buf, "%s/%s/%02d/%03d/%03d/%03d/%03d/%03d/%03d.%s",
        getPath().c_str(),
        spec.cacheId().c_str(),
        level,
        (x / 1000000),
        (x / 1000) % 1000,
        (x % 1000),
        (y / 1000000),
        (y / 1000) % 1000,
        (y % 1000),
        spec.format().c_str());

    return buf;
}
Esempio n. 3
0
std::string
TileMap::getURL(const osgEarth::TileKey& tilekey, bool invertY)
{
    if (!intersectsKey(tilekey))
    {
        //OE_NOTICE << LC << "No key intersection for tile key " << tilekey.str() << std::endl;
        return "";
    }

    unsigned int zoom = tilekey.getLevelOfDetail();

    unsigned int x, y;
    tilekey.getTileXY(x, y);

    //Some TMS like services swap the Y coordinate so 0,0 is the upper left rather than the lower left.  The normal TMS
    //specification has 0,0 at the bottom left, so inverting Y will make 0,0 in the upper left.
    //http://code.google.com/apis/maps/documentation/overlays.html#Google_Maps_Coordinates
    if (!invertY)
    {
        unsigned int numRows, numCols;
        tilekey.getProfile()->getNumTiles(tilekey.getLevelOfDetail(), numCols, numRows);
        y  = numRows - y - 1;
    }

    //OE_NOTICE << LC << "KEY: " << tilekey.str() << " level " << zoom << " ( " << x << ", " << y << ")" << std::endl;

    //Select the correct TileSet
    if ( _tileSets.size() > 0 )
    {
        for (TileSetList::iterator itr = _tileSets.begin(); itr != _tileSets.end(); ++itr)
        { 
            if (itr->getOrder() == zoom)
            {
                std::stringstream ss;
                std::string path = osgDB::getFilePath(_filename);
                ss << path << "/" << zoom << "/" << x << "/" << y << "." << _format.getExtension();
                //OE_NOTICE << LC << "Returning URL " << ss.str() << std::endl;
                std::string ssStr;
				ssStr = ss.str();
				return ssStr;
            }
        }
    }
    else // Just go with it. No way of knowing the max level.
    {
        std::stringstream ss;
        std::string path = osgDB::getFilePath(_filename);
        ss << path << "/" << zoom << "/" << x << "/" << y << "." << _format.getExtension();
        std::string ssStr;
		ssStr = ss.str();
		return ssStr;        
    }

    return "";
}
Esempio n. 4
0
    virtual void onTileAdded(const osgEarth::TileKey& tileKey, osg::Node* terrain, TerrainCallbackContext&)
    {           
        if ((int)tileKey.getLevelOfDetail() > _minLevel && _maxLevel < (int)tileKey.getLevelOfDetail())
        {
            osg::Vec3d position = _locator->getLocator()->getPosition();

            if (tileKey.getExtent().contains(position.x(), position.y()))
            {
                //Compute our location in geocentric
                const osg::EllipsoidModel* ellipsoid = tileKey.getProfile()->getSRS()->getEllipsoid();
                double x, y, z;            
                ellipsoid->convertLatLongHeightToXYZ(
                    osg::DegreesToRadians(position.y()), osg::DegreesToRadians(position.x()), 0,
                    x, y, z);
                //Compute the up vector
                osg::Vec3d up = ellipsoid->computeLocalUpVector(x, y, z );
                up.normalize();
                osg::Vec3d world(x, y, z);

                double segOffset = 50000;

                osg::Vec3d start = world + (up * segOffset);
                osg::Vec3d end = world - (up * segOffset);

                osgUtil::LineSegmentIntersector* i = new osgUtil::LineSegmentIntersector( start, end );

                osgUtil::IntersectionVisitor iv;            
                iv.setIntersector( i );
                terrain->accept( iv );

                osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections();
                if ( !results.empty() )
                {
                    const osgUtil::LineSegmentIntersector::Intersection& result = *results.begin();
                    osg::Vec3d hit = result.getWorldIntersectPoint();
                    double lat, lon, height;
                    ellipsoid->convertXYZToLatLongHeight(hit.x(), hit.y(), hit.z(), 
                        lat, lon, height);                
                    position.z() = height;
                    //OE_NOTICE << "Got hit, setting new height to " << height << std::endl;
                    _maxLevel = tileKey.getLevelOfDetail();
                    _locator->getLocator()->setPosition( position );
                }            
            }            
        }            

    }
Esempio n. 5
0
bool
TileSource::getBestAvailableTileKey(const osgEarth::TileKey& key,
                                    osgEarth::TileKey&       output) const
{
    // trivial reject
    if ( !key.valid() )
        return false;

    // trivial accept: no data extents = not enough info.
    if (_dataExtents.size() == 0)
    {
        output = key;
        return true;
    }

    // trivial reject: key doesn't intersect the union of data extents at all.
    if ( !getDataExtentsUnion().intersects(key.getExtent()) )
    {
        return false;
    }

    bool     intersects = false;
    unsigned highestLOD = 0;

    // We must use the equivalent lod b/c the key can be in any profile.
    int layerLOD = getProfile()->getEquivalentLOD( key.getProfile(), key.getLOD() );
    
    for (DataExtentList::const_iterator itr = _dataExtents.begin(); itr != _dataExtents.end(); ++itr)
    {
        // check for 2D intersection:
        if (key.getExtent().intersects( *itr ))
        {
            // check that the extent isn't higher-resolution than our key:
            if ( !itr->minLevel().isSet() || layerLOD >= itr->minLevel().get() )
            {
                // Got an intersetion; now test the LODs:
                intersects = true;
                
                // Is the high-LOD set? If not, there's not enough information
                // so just assume our key might be good.
                if ( itr->maxLevel().isSet() == false )
                {
                    output = key;
                    return true;
                }

                // Is our key at a lower or equal LOD than the max key in this extent?
                // If so, our key is good.
                else if ( layerLOD <= itr->maxLevel().get() )
                {
                    output = key;
                    return true;
                }

                // otherwise, record the highest encountered LOD that
                // intersects our key.
                else if ( itr->maxLevel().get() > highestLOD )
                {
                    highestLOD = itr->maxLevel().get();
                }
            }
        }
    }

    if ( intersects )
    {
        output = key.createAncestorKey( highestLOD );
        return true;
    }
    else
    {
        return false;
    }
}