bool ElevationPool::fetchTileFromMap(const TileKey& key, const ElevationLayerVector& layers, 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 envelope (" << keyToUse.str() << ")\n"; ok = layers.populateHeightFieldAndNormalMap(hf.get(), 0L, keyToUse, 0L, INTERP_BILINEAR, 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(); }
bool TerrainTileModelFactory::getOrCreateHeightField(const Map* map, const TileKey& key, ElevationSamplePolicy samplePolicy, ElevationInterpolation interpolation, unsigned border, osg::ref_ptr<osg::HeightField>& out_hf, osg::ref_ptr<NormalMap>& out_normalMap, ProgressCallback* progress) { // check the quick cache. HFCacheKey cachekey; cachekey._key = key; cachekey._revision = map->getDataModelRevision(); cachekey._samplePolicy = samplePolicy; if (progress) progress->stats()["hfcache_try_count"] += 1; bool hit = false; HFCache::Record rec; if ( _heightFieldCacheEnabled && _heightFieldCache.get(cachekey, rec) ) { out_hf = rec.value()._hf.get(); out_normalMap = rec.value()._normalMap.get(); 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; } if ( !out_hf.valid() ) { out_hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), 257, 257, // base tile size for elevation data border, // 1 sample border around the data makes it 259x259 true); // initialize to HAE (0.0) heights } if (!out_normalMap.valid()) { //OE_INFO << "TODO: check terrain reqs\n"; out_normalMap = new NormalMap(257, 257); // ImageUtils::createEmptyImage(257, 257); } ElevationLayerVector layers; map->getLayers(layers); bool populated = layers.populateHeightFieldAndNormalMap( out_hf.get(), out_normalMap.get(), key, map->getProfileNoVDatum(), // convertToHAE, INTERP_BILINEAR, progress ); #ifdef TREAT_ALL_ZEROS_AS_MISSING_TILE // check for a real tile with all zeros and treat it the same as non-existant data. if ( populated ) { bool isEmpty = true; for(osg::FloatArray::const_iterator f = out_hf->getFloatArray()->begin(); f != out_hf->getFloatArray()->end(); ++f) { if ( (*f) != 0.0f ) { isEmpty = false; break; } } if ( isEmpty ) { populated = false; } } #endif if ( populated ) { // Treat Plate Carre specially by scaling the height values. (There is no need // to do this with an empty heightfield) if (map->getSRS()->isPlateCarre()) { HeightFieldUtils::scaleHeightFieldToDegrees( out_hf.get() ); } // cache it. if (_heightFieldCacheEnabled ) { HFCacheValue newValue; newValue._hf = out_hf.get(); newValue._normalMap = out_normalMap.get(); _heightFieldCache.insert( cachekey, newValue ); } } return populated; }