本文整理汇总了C++中TileKey::getLOD方法的典型用法代码示例。如果您正苦于以下问题:C++ TileKey::getLOD方法的具体用法?C++ TileKey::getLOD怎么用?C++ TileKey::getLOD使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TileKey
的用法示例。
在下文中一共展示了TileKey::getLOD方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: getProfile
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;
}
示例2: getEquivalentLOD
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;
}
}
示例3:
void
TileModelFactory::buildElevation(const TileKey& key,
const MapFrame& frame,
bool accumulate,
bool buildTexture,
TileModel* model,
ProgressCallback* progress)
{
const MapInfo& mapInfo = frame.getMapInfo();
const osgEarth::ElevationInterpolation& interp =
frame.getMapOptions().elevationInterpolation().get();
// Request a heightfield from the map, falling back on lower resolution tiles
// if necessary (fallback=true)
osg::ref_ptr<osg::HeightField> hf;
bool isFallback = false;
// look up the parent's heightfield to use as a template
osg::ref_ptr<osg::HeightField> parentHF;
TileKey parentKey = key.createParentKey();
if ( accumulate )
{
osg::ref_ptr<TileNode> parentNode;
if (_liveTiles->get(parentKey, parentNode))
{
parentHF = parentNode->getTileModel()->_elevationData.getHeightField();
if ( _debug && key.getLOD() > 0 && !parentHF.valid() )
{
OE_NOTICE << LC << "Could not find a parent tile HF for " << key.str() << "\n";
}
}
}
// Make a new heightfield:
if (_meshHFCache->getOrCreateHeightField(frame, key, parentHF.get(), hf, isFallback, SAMPLE_FIRST_VALID, interp, progress))
{
model->_elevationData = TileModel::ElevationData(
hf,
GeoLocator::createForKey( key, mapInfo ),
isFallback );
// Edge normalization: requires adjacency information
if ( _terrainOptions.normalizeEdges() == true )
{
for( int x=-1; x<=1; x++ )
{
for( int y=-1; y<=1; y++ )
{
if ( x != 0 || y != 0 )
{
TileKey neighborKey = key.createNeighborKey(x, y);
if ( neighborKey.valid() )
{
osg::ref_ptr<osg::HeightField> neighborParentHF;
if ( accumulate )
{
TileKey neighborParentKey = neighborKey.createParentKey();
if (neighborParentKey == parentKey)
{
neighborParentHF = parentHF;
}
else
{
osg::ref_ptr<TileNode> neighborParentNode;
if (_liveTiles->get(neighborParentKey, neighborParentNode))
{
neighborParentHF = neighborParentNode->getTileModel()->_elevationData.getHeightField();
}
}
}
// only pull the tile if we have a valid parent HF for it -- otherwise
// you might get a flat tile when upsampling data.
if ( neighborParentHF.valid() )
{
osg::ref_ptr<osg::HeightField> hf;
if (_meshHFCache->getOrCreateHeightField(frame, neighborKey, neighborParentHF.get(), hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) )
{
model->_elevationData.setNeighbor( x, y, hf.get() );
}
}
}
}
}
}
// parent too.
if ( parentHF.valid() )
{
model->_elevationData.setParent( parentHF.get() );
}
}
if ( buildTexture )
{
model->generateElevationTexture();
}
}
//.........这里部分代码省略.........
示例4: exclusiveLock
bool
MBTilesTileSource::storeImage(const TileKey& key,
osg::Image* image,
ProgressCallback* progress)
{
if ( (getMode() & MODE_WRITE) == 0 )
return false;
Threading::ScopedMutexLock exclusiveLock(_mutex);
// encode the data stream:
std::stringstream buf;
osgDB::ReaderWriter::WriteResult wr;
if ( _forceRGB && ImageUtils::hasAlphaChannel(image) )
{
osg::ref_ptr<osg::Image> rgb = ImageUtils::convertToRGB8(image);
wr = _rw->writeImage(*(rgb.get()), buf, _dbOptions.get());
}
else
{
wr = _rw->writeImage(*image, buf, _dbOptions.get());
}
if ( wr.error() )
{
OE_WARN << LC << "Image encoding failed: " << wr.message() << std::endl;
return false;
}
std::string value = buf.str();
// compress if necessary:
if ( _compressor.valid() )
{
std::ostringstream output;
if ( !_compressor->compress(output, value) )
{
OE_WARN << LC << "Compressor failed" << std::endl;
return false;
}
value = output.str();
}
int z = key.getLOD();
int x = key.getTileX();
int y = key.getTileY();
// flip Y axis
unsigned int numRows, numCols;
key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);
y = numRows - y - 1;
// Prep the insert statement:
sqlite3_stmt* insert = NULL;
std::string query = "INSERT OR REPLACE INTO tiles (zoom_level, tile_column, tile_row, tile_data) VALUES (?, ?, ?, ?)";
int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &insert, 0L );
if ( rc != SQLITE_OK )
{
OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
return false;
}
// bind parameters:
sqlite3_bind_int( insert, 1, z );
sqlite3_bind_int( insert, 2, x );
sqlite3_bind_int( insert, 3, y );
// bind the data blob:
sqlite3_bind_blob( insert, 4, value.c_str(), value.length(), SQLITE_STATIC );
// run the sql.
bool ok = true;
int tries = 0;
do {
rc = sqlite3_step(insert);
}
while (++tries < 100 && (rc == SQLITE_BUSY || rc == SQLITE_LOCKED));
if (SQLITE_OK != rc && SQLITE_DONE != rc)
{
#if SQLITE_VERSION_NUMBER >= 3007015
OE_WARN << LC << "Failed query: " << query << "(" << rc << ")" << sqlite3_errstr(rc) << "; " << sqlite3_errmsg(_database) << std::endl;
#else
OE_WARN << LC << "Failed query: " << query << "(" << rc << ")" << rc << "; " << sqlite3_errmsg(_database) << std::endl;
#endif
ok = false;
}
sqlite3_finalize( insert );
return ok;
}
示例5:
bool
HeightFieldCache::getOrCreateHeightField(const MapFrame& frame,
const TileKey& key,
//bool cummulative,
const osg::HeightField* parent_hf,
osg::ref_ptr<osg::HeightField>& out_hf,
bool& out_isFallback,
ElevationSamplePolicy samplePolicy,
ElevationInterpolation interp,
ProgressCallback* progress )
{
// default
out_isFallback = false;
// check the quick cache.
HFKey cachekey;
cachekey._key = key;
cachekey._revision = frame.getRevision();
cachekey._samplePolicy = samplePolicy;
if (progress)
progress->stats()["hfcache_try_count"] += 1;
bool hit = false;
LRUCache<HFKey,HFValue>::Record rec;
if ( _cache.get(cachekey, rec) )
{
out_hf = rec.value()._hf.get();
out_isFallback = rec.value()._isFallback;
if (progress)
{
progress->stats()["hfcache_hit_count"] += 1;
progress->stats()["hfcache_hit_rate"] = progress->stats()["hfcache_hit_count"]/progress->stats()["hfcache_try_count"];
}
return true;
}
// Find the parent tile and start with its heightfield.
if ( parent_hf )
{
TileKey parentKey = key.createParentKey();
out_hf = HeightFieldUtils::createSubSample(
parent_hf,
parentKey.getExtent(),
key.getExtent(),
interp );
if ( !out_hf.valid() && ((int)key.getLOD())-1 > _firstLOD )
{
// This most likely means that a parent tile expired while we were building the child.
// No harm done in that case as this tile will soo be discarded as well.
OE_DEBUG << "MP HFC: Unable to find tile " << key.str() << " in the live tile registry"
<< std::endl;
return false;
}
}
if ( !out_hf.valid() )
{
//TODO.
// This sets the elevation tile size; query size for all tiles.
out_hf = HeightFieldUtils::createReferenceHeightField(
key.getExtent(), _tileSize, _tileSize, true );
}
bool populated = frame.populateHeightField(
out_hf,
key,
true, // convertToHAE
samplePolicy,
progress );
// Treat Plate Carre specially by scaling the height values. (There is no need
// to do this with an empty heightfield)
const MapInfo& mapInfo = frame.getMapInfo();
if ( mapInfo.isPlateCarre() )
{
HeightFieldUtils::scaleHeightFieldToDegrees( out_hf.get() );
}
// cache it.
HFValue cacheval;
cacheval._hf = out_hf.get();
cacheval._isFallback = !populated;
_cache.insert( cachekey, cacheval );
out_isFallback = !populated;
return true;
}
示例6: getProfile
void
ElevationLayer::assembleHeightField(const TileKey& key,
osg::ref_ptr<osg::HeightField>& out_hf,
osg::ref_ptr<NormalMap>& out_normalMap,
ProgressCallback* progress)
{
// Collect the heightfields for each of the intersecting tiles.
GeoHeightFieldVector heightFields;
//Determine the intersecting keys
std::vector< TileKey > intersectingTiles;
if (key.getLOD() > 0u)
{
getProfile()->getIntersectingTiles(key, intersectingTiles);
}
else
{
// LOD is zero - check whether the LOD mapping went out of range, and if so,
// fall back until we get valid tiles. This can happen when you have two
// profiles with very different tile schemes, and the "equivalent LOD"
// surpasses the max data LOD of the tile source.
unsigned numTilesThatMayHaveData = 0u;
int intersectionLOD = getProfile()->getEquivalentLOD(key.getProfile(), key.getLOD());
while (numTilesThatMayHaveData == 0u && intersectionLOD >= 0)
{
intersectingTiles.clear();
getProfile()->getIntersectingTiles(key.getExtent(), intersectionLOD, intersectingTiles);
for (unsigned int i = 0; i < intersectingTiles.size(); ++i)
{
const TileKey& layerKey = intersectingTiles[i];
if (mayHaveData(layerKey) == true)
{
++numTilesThatMayHaveData;
}
}
--intersectionLOD;
}
}
// collect heightfield for each intersecting key. Note, we're hitting the
// underlying tile source here, so there's no vetical datum shifts happening yet.
// we will do that later.
if ( intersectingTiles.size() > 0 )
{
for (unsigned int i = 0; i < intersectingTiles.size(); ++i)
{
const TileKey& layerKey = intersectingTiles[i];
if ( isKeyInLegalRange(layerKey) )
{
osg::ref_ptr<osg::HeightField> hf;
osg::ref_ptr<NormalMap> normalMap;
createImplementation(layerKey, hf, normalMap, progress);
if (hf.valid())
{
heightFields.push_back( GeoHeightField(hf.get(), normalMap.get(), layerKey.getExtent()) );
}
}
}
// If we actually got a HeightField, resample/reproject it to match the incoming TileKey's extents.
if (heightFields.size() > 0)
{
unsigned int width = 0;
unsigned int height = 0;
for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr)
{
if (itr->getHeightField()->getNumColumns() > width)
width = itr->getHeightField()->getNumColumns();
if (itr->getHeightField()->getNumRows() > height)
height = itr->getHeightField()->getNumRows();
}
//Now sort the heightfields by resolution to make sure we're sampling the highest resolution one first.
std::sort( heightFields.begin(), heightFields.end(), GeoHeightField::SortByResolutionFunctor());
out_hf = new osg::HeightField();
out_hf->allocate(width, height);
out_normalMap = new NormalMap(width, height);
//Go ahead and set up the heightfield so we don't have to worry about it later
double minx, miny, maxx, maxy;
key.getExtent().getBounds(minx, miny, maxx, maxy);
double dx = (maxx - minx)/(double)(width-1);
double dy = (maxy - miny)/(double)(height-1);
//Create the new heightfield by sampling all of them.
for (unsigned int c = 0; c < width; ++c)
{
double x = minx + (dx * (double)c);
for (unsigned r = 0; r < height; ++r)
{
//.........这里部分代码省略.........
示例7: bestKey
bool
ElevationLayerVector::populateHeightFieldAndNormalMap(osg::HeightField* hf,
NormalMap* normalMap,
const TileKey& key,
const Profile* haeProfile,
ElevationInterpolation interpolation,
ProgressCallback* progress ) const
{
// heightfield must already exist.
if ( !hf )
return false;
METRIC_SCOPED("ElevationLayer.populateHeightField");
// if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
// the map profile has a vertical datum. This is the usual case when building the 3D
// terrain, for example. Construct a temporary key that doesn't have the vertical
// datum info and use that to query the elevation data.
TileKey keyToUse = key;
if ( haeProfile )
{
keyToUse = TileKey(key.getLOD(), key.getTileX(), key.getTileY(), haeProfile );
}
// Collect the valid layers for this tile.
LayerDataVector contenders;
LayerDataVector offsets;
#ifdef ANALYZE
struct LayerAnalysis {
LayerAnalysis() : samples(0), used(false), failed(false), fallback(false), actualKeyValid(true) { }
int samples; bool used; bool failed; bool fallback; bool actualKeyValid; std::string message;
};
std::map<ElevationLayer*, LayerAnalysis> layerAnalysis;
#endif
// Track the number of layers that would return fallback data.
unsigned numFallbackLayers = 0;
// Check them in reverse order since the highest priority is last.
for (int i = size()-1; i>=0; --i)
//for(ElevationLayerVector::const_reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
{
ElevationLayer* layer = (*this)[i].get(); //i->get();
if ( layer->getEnabled() && layer->getVisible() )
{
// calculate the resolution-mapped key (adjusted for tile resolution differential).
TileKey mappedKey = keyToUse.mapResolution(
hf->getNumColumns(),
layer->getTileSize() );
bool useLayer = true;
TileKey bestKey( mappedKey );
// Check whether the non-mapped key is valid according to the user's min/max level settings:
if ( !layer->isKeyInLegalRange(key) )
{
useLayer = false;
}
// Find the "best available" mapped key from the tile source:
else
{
bestKey = layer->getBestAvailableTileKey(mappedKey);
if (bestKey.valid())
{
// If the bestKey is not the mappedKey, this layer is providing
// fallback data (data at a lower resolution than requested)
if ( mappedKey != bestKey )
{
numFallbackLayers++;
}
}
else
{
useLayer = false;
}
}
if ( useLayer )
{
if ( layer->isOffset() )
{
offsets.push_back(LayerData());
LayerData& ld = offsets.back();
ld.layer = layer;
ld.key = bestKey;
ld.index = i;
}
else
{
contenders.push_back(LayerData());
LayerData& ld = contenders.back();
ld.layer = layer;
ld.key = bestKey;
ld.index = i;
}
#ifdef ANALYZE
//.........这里部分代码省略.........
示例8: getOrCreateHeightField
void
TerrainTileModelFactory::addElevation(TerrainTileModel* model,
const Map* map,
const TileKey& key,
const CreateTileModelFilter& filter,
unsigned border,
ProgressCallback* progress)
{
// make an elevation layer.
OE_START_TIMER(fetch_elevation);
if (!filter.empty() && !filter.elevation().isSetTo(true))
return;
const osgEarth::ElevationInterpolation& interp =
map->getMapOptions().elevationInterpolation().get();
// Request a heightfield from the map.
osg::ref_ptr<osg::HeightField> mainHF;
osg::ref_ptr<NormalMap> normalMap;
bool hfOK = getOrCreateHeightField(map, key, SAMPLE_FIRST_VALID, interp, border, mainHF, normalMap, progress) && mainHF.valid();
if (hfOK == false && key.getLOD() == _options.firstLOD().get())
{
OE_DEBUG << LC << "No HF at key " << key.str() << ", making placeholder" << std::endl;
mainHF = new osg::HeightField();
mainHF->allocate(1, 1);
mainHF->setHeight(0, 0, 0.0f);
hfOK = true;
}
if (hfOK && mainHF.valid())
{
osg::ref_ptr<TerrainTileElevationModel> layerModel = new TerrainTileElevationModel();
layerModel->setHeightField( mainHF.get() );
// pre-calculate the min/max heights:
for( unsigned col = 0; col < mainHF->getNumColumns(); ++col )
{
for( unsigned row = 0; row < mainHF->getNumRows(); ++row )
{
float h = mainHF->getHeight(col, row);
if ( h > layerModel->getMaxHeight() )
layerModel->setMaxHeight( h );
if ( h < layerModel->getMinHeight() )
layerModel->setMinHeight( h );
}
}
// needed for normal map generation
model->heightFields().setNeighbor(0, 0, mainHF.get());
// convert the heightfield to a 1-channel 32-bit fp image:
ImageToHeightFieldConverter conv;
osg::Image* hfImage = conv.convertToR32F(mainHF.get());
if ( hfImage )
{
// Made an image, so store this as a texture with no matrix.
osg::Texture* texture = createElevationTexture( hfImage );
layerModel->setTexture( texture );
model->elevationModel() = layerModel.get();
}
if (normalMap.valid())
{
TerrainTileImageLayerModel* layerModel = new TerrainTileImageLayerModel();
layerModel->setName( "oe_normal_map" );
// Made an image, so store this as a texture with no matrix.
osg::Texture* texture = createNormalTexture(normalMap.get());
layerModel->setTexture( texture );
model->normalModel() = layerModel;
}
}
if (progress)
progress->stats()["fetch_elevation_time"] += OE_STOP_TIMER(fetch_elevation);
}
示例9: createCoverageTexture
void
TerrainTileModelFactory::addColorLayers(TerrainTileModel* model,
const Map* map,
const TerrainEngineRequirements* reqs,
const TileKey& key,
const CreateTileModelFilter& filter,
ProgressCallback* progress)
{
OE_START_TIMER(fetch_image_layers);
int order = 0;
LayerVector layers;
map->getLayers(layers);
for (LayerVector::const_iterator i = layers.begin(); i != layers.end(); ++i)
{
Layer* layer = i->get();
if (layer->getRenderType() != layer->RENDERTYPE_TERRAIN_SURFACE)
continue;
if (!layer->getEnabled())
continue;
if (!filter.accept(layer))
continue;
ImageLayer* imageLayer = dynamic_cast<ImageLayer*>(layer);
if (imageLayer)
{
osg::Texture* tex = 0L;
osg::Matrixf textureMatrix;
if (imageLayer->isKeyInLegalRange(key) && imageLayer->mayHaveDataInExtent(key.getExtent()))
{
if (imageLayer->createTextureSupported())
{
tex = imageLayer->createTexture( key, progress, textureMatrix );
}
else
{
GeoImage geoImage = imageLayer->createImage( key, progress );
if ( geoImage.valid() )
{
if ( imageLayer->isCoverage() )
tex = createCoverageTexture(geoImage.getImage(), imageLayer);
else
tex = createImageTexture(geoImage.getImage(), imageLayer);
}
}
}
// if this is the first LOD, and the engine requires that the first LOD
// be populated, make an empty texture if we didn't get one.
if (tex == 0L &&
_options.firstLOD() == key.getLOD() &&
reqs && reqs->fullDataAtFirstLodRequired())
{
tex = _emptyTexture.get();
}
if (tex)
{
tex->setName(model->getKey().str());
TerrainTileImageLayerModel* layerModel = new TerrainTileImageLayerModel();
layerModel->setImageLayer(imageLayer);
layerModel->setTexture(tex);
layerModel->setMatrix(new osg::RefMatrixf(textureMatrix));
model->colorLayers().push_back(layerModel);
if (imageLayer->isShared())
{
model->sharedLayers().push_back(layerModel);
}
if (imageLayer->isDynamic())
{
model->setRequiresUpdateTraverse(true);
}
}
}
else // non-image kind of TILE layer:
{
TerrainTileColorLayerModel* colorModel = new TerrainTileColorLayerModel();
colorModel->setLayer(layer);
model->colorLayers().push_back(colorModel);
}
}
if (progress)
progress->stats()["fetch_imagery_time"] += OE_STOP_TIMER(fetch_image_layers);
}
示例10: GeoImage
GeoImage
ImageLayer::createImageInKeyProfile( const TileKey& key, ProgressCallback* progress, bool forceFallback, bool& out_isFallback )
{
GeoImage result;
out_isFallback = false;
// If the layer is disabled, bail out.
if ( !getEnabled() )
{
return GeoImage::INVALID;
}
// Check the max data level, which limits the LOD of available data.
if ( _runtimeOptions.maxDataLevel().isSet() && key.getLOD() > _runtimeOptions.maxDataLevel().value() )
{
return GeoImage::INVALID;
}
// Check for a "Minumum level" setting on this layer. If we are before the
// min level, just return the empty image. Do not cache empties
if ( _runtimeOptions.minLevel().isSet() && key.getLOD() < _runtimeOptions.minLevel().value() )
{
return GeoImage( _emptyImage.get(), key.getExtent() );
}
// Check for a "Minimum resolution" setting on the layer. If we are before the
// min resolution, return the empty image. Do not cache empties.
if ( _runtimeOptions.minResolution().isSet() )
{
double keyres = key.getExtent().width() / getTileSize();
double keyresInLayerProfile = key.getProfile()->getSRS()->transformUnits(keyres, getProfile()->getSRS());
if ( keyresInLayerProfile > _runtimeOptions.minResolution().value() )
{
return GeoImage( _emptyImage.get(), key.getExtent() );
}
}
OE_DEBUG << LC << "create image for \"" << key.str() << "\", ext= "
<< key.getExtent().toString() << std::endl;
// locate the cache bin for the target profile for this layer:
CacheBin* cacheBin = getCacheBin( key.getProfile() );
// validate that we have either a valid tile source, or we're cache-only.
if ( ! (getTileSource() || (isCacheOnly() && cacheBin) ) )
{
OE_WARN << LC << "Error: layer does not have a valid TileSource, cannot create image " << std::endl;
_runtimeOptions.enabled() = false;
return GeoImage::INVALID;
}
// validate the existance of a valid layer profile (unless we're in cache-only mode, in which
// case there is no layer profile)
if ( !isCacheOnly() && !getProfile() )
{
OE_WARN << LC << "Could not establish a valid profile" << std::endl;
_runtimeOptions.enabled() = false;
return GeoImage::INVALID;
}
// First, attempt to read from the cache. Since the cached data is stored in the
// map profile, we can try this first.
if ( cacheBin && getCachePolicy().isCacheReadable() )
{
ReadResult r = cacheBin->readImage( key.str(), getCachePolicy().getMinAcceptTime() );
if ( r.succeeded() )
{
ImageUtils::normalizeImage( r.getImage() );
return GeoImage( r.releaseImage(), key.getExtent() );
}
//else if ( r.code() == ReadResult::RESULT_EXPIRED )
//{
// OE_INFO << LC << getName() << " : " << key.str() << " record expired!" << std::endl;
//}
}
// The data was not in the cache. If we are cache-only, fail sliently
if ( isCacheOnly() )
{
return GeoImage::INVALID;
}
// Get an image from the underlying TileSource.
result = createImageFromTileSource( key, progress, forceFallback, out_isFallback );
// Normalize the image if necessary
if ( result.valid() )
{
ImageUtils::normalizeImage( result.getImage() );
}
// If we got a result, the cache is valid and we are caching in the map profile, write to the map cache.
if (result.valid() &&
//JB: Removed the check to not write out fallback data. If you have a low resolution base dataset (max lod 3) and a high resolution insert (max lod 22)
// then the low res data needs to "fallback" from LOD 4 - 22 so you can display the high res inset. If you don't cache these intermediate tiles then
// performance can suffer generating all those fallback tiles, especially if you have to do reprojection or mosaicing.
//!out_isFallback &&
//.........这里部分代码省略.........
示例11: bestKey
bool
ElevationLayerVector::populateHeightField(osg::HeightField* hf,
const TileKey& key,
const Profile* haeProfile,
ElevationInterpolation interpolation,
ProgressCallback* progress ) const
{
// heightfield must already exist.
if ( !hf )
return false;
// if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
// the map profile has a vertical datum. This is the usual case when building the 3D
// terrain, for example. Construct a temporary key that doesn't have the vertical
// datum info and use that to query the elevation data.
TileKey keyToUse = key;
if ( haeProfile )
{
keyToUse = TileKey(key.getLOD(), key.getTileX(), key.getTileY(), haeProfile );
}
// Collect the valid layers for this tile.
LayerAndKeyVector contenders;
LayerAndKeyVector offsets;
// Track the number of layers that would return fallback data.
unsigned numFallbackLayers = 0;
// Check them in reverse order since the highest priority is last.
for(ElevationLayerVector::const_reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
{
ElevationLayer* layer = i->get();
if ( layer->getEnabled() && layer->getVisible() )
{
// calculate the resolution-mapped key (adjusted for tile resolution differential).
TileKey mappedKey = keyToUse.mapResolution(
hf->getNumColumns(),
layer->getTileSize() );
bool useLayer = true;
TileKey bestKey( mappedKey );
// Is there a tilesource? If not we are cache-only and cannot reject the layer.
if ( layer->getTileSource() )
{
// Check whether the non-mapped key is valid according to the user's min/max level settings:
if ( !layer->isKeyInRange(key) )
{
useLayer = false;
}
// Find the "best available" mapped key from the tile source:
else
{
if ( layer->getTileSource()->getBestAvailableTileKey(mappedKey, bestKey) )
{
// If the bestKey is not the mappedKey, this layer is providing
// fallback data (data at a lower resolution than requested)
if ( mappedKey != bestKey )
{
numFallbackLayers++;
}
}
else
{
useLayer = false;
}
}
}
if ( useLayer )
{
if ( layer->isOffset() )
{
offsets.push_back( std::make_pair(layer, bestKey) );
}
else
{
contenders.push_back( std::make_pair(layer, bestKey) );
}
}
}
}
// nothing? bail out.
if ( contenders.empty() && offsets.empty() )
{
return false;
}
// if everything is fallback data, bail out.
if ( contenders.size() + offsets.size() == numFallbackLayers )
{
return false;
}
// Sample the layers into our target.
unsigned numColumns = hf->getNumColumns();
//.........这里部分代码省略.........
示例12: heightFields
bool
ElevationLayerVector::populateHeightField(osg::HeightField* hf,
const TileKey& key,
const Profile* haeProfile,
ElevationInterpolation interpolation,
ProgressCallback* progress ) const
{
// heightfield must already exist.
if ( !hf )
return false;
// if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
// the map profile has a vertical datum. This is the usual case when building the 3D
// terrain, for example. Construct a temporary key that doesn't have the vertical
// datum info and use that to query the elevation data.
TileKey keyToUse = key;
if ( haeProfile )
{
keyToUse = TileKey(key.getLOD(), key.getTileX(), key.getTileY(), haeProfile );
}
// Collect the valid layers for this tile.
ElevationLayerVector contenders;
ElevationLayerVector offsets;
for(ElevationLayerVector::const_reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
{
ElevationLayer* layer = i->get();
if ( layer->getEnabled() && layer->getVisible() )
{
// calculate the resolution-mapped key (adjusted for tile resolution differential).
TileKey mappedKey =
keyToUse.mapResolution(hf->getNumColumns(), layer->getTileSize());
// Note: isKeyInRange tests the key, but haData tests the mapped key.
// I think that's right!
if ((layer->getTileSource() == 0L) ||
(layer->isKeyInRange(key) && layer->getTileSource()->hasData(mappedKey)))
{
if (layer->isOffset())
offsets.push_back(layer);
else
contenders.push_back(layer);
}
}
}
// nothing? bail out.
if ( contenders.empty() && offsets.empty() )
{
return false;
}
// Sample the layers into our target.
unsigned numColumns = hf->getNumColumns();
unsigned numRows = hf->getNumRows();
double xmin = key.getExtent().xMin();
double ymin = key.getExtent().yMin();
double dx = key.getExtent().width() / (double)(numColumns-1);
double dy = key.getExtent().height() / (double)(numRows-1);
// We will load the actual heightfields on demand. We might not need them all.
GeoHeightFieldVector heightFields(contenders.size());
GeoHeightFieldVector offsetFields(offsets.size());
std::vector<bool> heightFailed (contenders.size(), false);
std::vector<bool> offsetFailed(offsets.size(), false);
const SpatialReference* keySRS = keyToUse.getProfile()->getSRS();
bool realData = false;
for (unsigned c = 0; c < numColumns; ++c)
{
double x = xmin + (dx * (double)c);
for (unsigned r = 0; r < numRows; ++r)
{
double y = ymin + (dy * (double)r);
// Collect elevations from each layer as necessary.
bool resolved = false;
for(int i=0; i<contenders.size() && !resolved; ++i)
{
if ( heightFailed[i] )
continue;
GeoHeightField& layerHF = heightFields[i];
if ( !layerHF.valid() )
{
TileKey mappedKey =
keyToUse.mapResolution(hf->getNumColumns(), contenders[i]->getTileSize());
layerHF = contenders[i]->createHeightField(mappedKey, progress);
if ( !layerHF.valid() )
{
heightFailed[i] = true;
continue;
}
}
//.........这里部分代码省略.........
示例13: establish
void
ModelSplatter::operator()(const TileKey& key, osg::Node* node)
{
TerrainTileNode* tile = osgEarth::findTopMostNodeOfType<TerrainTileNode>(node);
if ( !tile )
return;
if ( key.getLOD() >= _minLOD && _model.valid() )
{
// make sure the correct model is loaded
establish();
// elevation texture and matrix are required
osg::Texture* elevationTex = tile->getElevationTexture();
if ( !elevationTex )
{
//OE_WARN << LC << "No elevation texture for key " << key.str() << "\n";
return;
}
osg::RefMatrix* elevationTexMat = tile->getElevationTextureMatrix();
if ( !elevationTexMat )
{
//OE_WARN << LC << "No elevation texture matrix for key " << key.str() << "\n";
return;
}
tile->addChild( _model.get() );
osg::StateSet* ss = tile->getOrCreateStateSet();
// first, a rotation vector to make trees point up.
GeoPoint p;
key.getExtent().getCentroid(p);
osg::Vec3d up;
p.createWorldUpVector(up);
osg::Quat q;
q.makeRotate(osg::Vec3d(0,0,1), up);
osg::Matrixd zup = osg::Matrixd::rotate(q);
// matrices to resolve the weird terrain localization into a usable LTP.
osg::Matrix tile2world = tile->getMatrix();
osg::Matrix world2ltp;
p.createWorldToLocal(world2ltp);
osg::Matrix local2ltp = tile2world * world2ltp;
osg::Matrix ltp2local;
ltp2local.invert(local2ltp);
// after inverting the matrix, combine the ZUP (optimization)
local2ltp.preMult( zup );
ss->addUniform( new osg::Uniform("oe_trees_local2ltp", osg::Matrixf(local2ltp)) );
ss->addUniform( new osg::Uniform("oe_trees_ltp2local", osg::Matrixf(ltp2local)) );
// calculate the scatter area:
float h = key.getExtent().height() * 111320.0f;
float w = key.getExtent().width() * 111320.0f * cos(fabs(osg::DegreesToRadians(p.y())));
ss->addUniform( new osg::Uniform("oe_trees_span", osg::Vec2f(w,h)) );
ss->setTextureAttributeAndModes(2, tile->getElevationTexture(), 1);
ss->addUniform( new osg::Uniform("oe_terrain_tex_matrix", osg::Matrixf(*elevationTexMat)) );
}
}
示例14: bestKey
bool
ElevationLayerVector::populateHeightField(osg::HeightField* hf,
const TileKey& key,
const Profile* haeProfile,
ElevationInterpolation interpolation,
ProgressCallback* progress ) const
{
//osg::Timer_t startTime = osg::Timer::instance()->tick();
// heightfield must already exist.
if ( !hf )
return false;
// if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
// the map profile has a vertical datum. This is the usual case when building the 3D
// terrain, for example. Construct a temporary key that doesn't have the vertical
// datum info and use that to query the elevation data.
TileKey keyToUse = key;
if ( haeProfile )
{
keyToUse = TileKey(key.getLOD(), key.getTileX(), key.getTileY(), haeProfile );
}
// Collect the valid layers for this tile.
LayerAndKeyVector contenders;
LayerAndKeyVector offsets;
// Track the number of layers that would return fallback data.
unsigned numFallbackLayers = 0;
// Check them in reverse order since the highest priority is last.
for(ElevationLayerVector::const_reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
{
ElevationLayer* layer = i->get();
if ( layer->getEnabled() && layer->getVisible() )
{
// calculate the resolution-mapped key (adjusted for tile resolution differential).
TileKey mappedKey = keyToUse.mapResolution(
hf->getNumColumns(),
layer->getTileSize() );
bool useLayer = true;
TileKey bestKey( mappedKey );
// Is there a tilesource? If not we are cache-only and cannot reject the layer.
if ( layer->getTileSource() )
{
// Check whether the non-mapped key is valid according to the user's min/max level settings:
if ( !layer->isKeyInRange(key) )
{
useLayer = false;
}
// Find the "best available" mapped key from the tile source:
else
{
if ( layer->getTileSource()->getBestAvailableTileKey(mappedKey, bestKey) )
{
// If the bestKey is not the mappedKey, this layer is providing
// fallback data (data at a lower resolution than requested)
if ( mappedKey != bestKey )
{
numFallbackLayers++;
}
}
else
{
useLayer = false;
}
}
}
if ( useLayer )
{
if ( layer->isOffset() )
{
offsets.push_back( std::make_pair(layer, bestKey) );
}
else
{
contenders.push_back( std::make_pair(layer, bestKey) );
}
}
}
}
// nothing? bail out.
if ( contenders.empty() && offsets.empty() )
{
return false;
}
// if everything is fallback data, bail out.
if ( contenders.size() + offsets.size() == numFallbackLayers )
{
return false;
}
// Sample the layers into our target.
//.........这里部分代码省略.........
示例15: if
TileKey
TerrainLayer::getBestAvailableTileKey(const TileKey& key) const
{
// trivial reject
if ( !key.valid() )
return TileKey::INVALID;
unsigned MDL = options().maxDataLevel().get();
// 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();
// Check against level extrema:
if (localLOD < options().minLevel().get() || localLOD > options().maxLevel().get())
{
return TileKey::INVALID;
}
// 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 TileKey::INVALID;
}
if (options().minResolution().isSet() &&
options().minResolution().value() < resLayer)
{
return TileKey::INVALID;
}
}
}
// Next check against the data extents.
const DataExtentList& de = getDataExtents();
// If we have mo data extents available, just return the MDL-limited input key.
if (de.empty())
{
return localLOD > MDL ? key.createAncestorKey(MDL) : key;
}
// Reject if the extents don't overlap at all.
if (!getDataExtentsUnion().intersects(key.getExtent()))
{
return TileKey::INVALID;
}
bool intersects = false;
unsigned highestLOD = 0;
// Check each data extent in turn:
for (DataExtentList::const_iterator itr = de.begin(); itr != de.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() || localLOD >= (int)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 )
{
return localLOD > MDL ? key.createAncestorKey(MDL) : key;
}
// Is our key at a lower or equal LOD than the max key in this extent?
// If so, our key is good.
else if ( localLOD <= (int)itr->maxLevel().get() )
{
return localLOD > MDL ? key.createAncestorKey(MDL) : key;
}
// otherwise, record the highest encountered LOD that
// intersects our key.
else if ( itr->maxLevel().get() > highestLOD )
{
highestLOD = itr->maxLevel().get();
}
}
}
}
if ( intersects )
//.........这里部分代码省略.........