// override // Creates an image. osg::Image* createImage(const TileKey& key, ProgressCallback* progress ) { if ( !_imageLayer.valid() || !_featureSource.valid() ) return 0L; // fetch the image for this key: GeoImage image = _imageLayer->createImage(key, progress); if ( !image.valid() ) return 0L; // fetch a set of features for this key. The features are in their // own SRS, so we need to transform: const SpatialReference* featureSRS = _featureSource->getFeatureProfile()->getSRS(); GeoExtent extentInFeatureSRS = key.getExtent().transform( featureSRS ); // assemble a spatial query. It helps if your features have a spatial index. Query query; query.bounds() = extentInFeatureSRS.bounds(); //query.expression() = ... // SQL expression compatible with data source osg::ref_ptr<FeatureCursor> cursor = _featureSource->createFeatureCursor(query); // create a new image to return. osg::Image* output = new osg::Image(); //output->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE); // do your magic here. return output; }
/* method: contains of class GeoExtent */ static int tolua_Lua_ScriptEngine_tolua_GeoExtent_contains02(lua_State* tolua_S) { tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"GeoExtent",0,&tolua_err) || !tolua_isusertype(tolua_S,2,"GeoExtent",0,&tolua_err) || !tolua_isnoobj(tolua_S,3,&tolua_err) ) goto tolua_lerror; else { GeoExtent* self = (GeoExtent*) tolua_tousertype(tolua_S,1,0); GeoExtent e = *((GeoExtent*) tolua_tousertype(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'contains'",NULL); #endif { bool tolua_ret = (bool) self->contains(e); tolua_pushboolean(tolua_S,(bool)tolua_ret); } } return 1; tolua_lerror: return tolua_Lua_ScriptEngine_tolua_GeoExtent_contains01(tolua_S); }
/* method: getArea of class GeoExtent */ static int tolua_Lua_ScriptEngine_tolua_GeoExtent_getArea00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"GeoExtent",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { GeoExtent* self = (GeoExtent*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'getArea'",NULL); #endif { double tolua_ret = (double) self->getArea(); tolua_pushnumber(tolua_S,(double)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'getArea'.",&tolua_err); return 0; #endif }
bool extentInsideOrOnLine( const GeoExtent& p, const GeoPoint& s1, const GeoPoint& s2 ) { return pointInsideOrOnLine( p.getSouthwest(), s1, s2 ) && pointInsideOrOnLine( p.getNortheast(), s1, s2 ); }
/* method: contains of class GeoExtent */ static int tolua_Lua_ScriptEngine_tolua_GeoExtent_contains00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"GeoExtent",0,&tolua_err) || !tolua_isnumber(tolua_S,2,0,&tolua_err) || !tolua_isnumber(tolua_S,3,0,&tolua_err) || !tolua_isnoobj(tolua_S,4,&tolua_err) ) goto tolua_lerror; else #endif { GeoExtent* self = (GeoExtent*) tolua_tousertype(tolua_S,1,0); double x = ((double) tolua_tonumber(tolua_S,2,0)); double y = ((double) tolua_tonumber(tolua_S,3,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'contains'",NULL); #endif { bool tolua_ret = (bool) self->contains(x,y); tolua_pushboolean(tolua_S,(bool)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'contains'.",&tolua_err); return 0; #endif }
GeoExtent OGR_SpatialReference::transform( const GeoExtent& input ) const { GeoPoint sw = transform( input.getSouthwest() ); GeoPoint ne = transform( input.getNortheast() ); return GeoExtent( sw, ne ); }
void FeatureNode::updateClusterCulling() { // install a cluster culler. if ( getMapNode()->isGeocentric() && _clusterCulling && !_clusterCullingCallback) { const GeoExtent& ccExtent = _extent; if ( ccExtent.isValid() ) { // if the extent is more than 90 degrees, bail GeoExtent geodeticExtent = ccExtent.transform( ccExtent.getSRS()->getGeographicSRS() ); if ( geodeticExtent.width() < 90.0 && geodeticExtent.height() < 90.0 ) { // get the geocentric tile center: osg::Vec3d tileCenter; ccExtent.getCentroid( tileCenter.x(), tileCenter.y() ); osg::Vec3d centerECEF; ccExtent.getSRS()->transform( tileCenter, getMapNode()->getMapSRS()->getECEF(), centerECEF ); _clusterCullingCallback = ClusterCullingFactory::create2( this, centerECEF ); if ( _clusterCullingCallback ) this->addCullCallback( _clusterCullingCallback ); } } } else if (!_clusterCulling && _clusterCullingCallback) { this->removeCullCallback( _clusterCullingCallback ); _clusterCullingCallback = 0; } }
void UnifiedCubeProfile::getIntersectingTiles(const GeoExtent& remoteExtent, unsigned localLOD, std::vector<TileKey>& out_intersectingKeys ) const { if ( getSRS()->isHorizEquivalentTo( remoteExtent.getSRS() ) ) { addIntersectingTiles( remoteExtent, localLOD, out_intersectingKeys ); } else { // the cube profile is non-contiguous. so there may be multiple local extents required // to fully intersect the remote extent. // first transform the remote extent to lat/long. GeoExtent remoteExtent_gcs = remoteExtent.getSRS()->isGeographic() ? remoteExtent : remoteExtent.transform( remoteExtent.getSRS()->getGeographicSRS() ); // Chop the input extent into three separate extents: for the equatorial, north polar, // and south polar tile regions. for( int face=0; face<6; ++face ) { GeoExtent partExtent_gcs = _faceExtent_gcs[face].intersectionSameSRS( remoteExtent_gcs ); if ( partExtent_gcs.isValid() ) { GeoExtent partExtent = transformGcsExtentOnFace( partExtent_gcs, face ); addIntersectingTiles( partExtent, localLOD, out_intersectingKeys ); } } } }
bool GeoExtent::splitAcrossDateLine( GeoExtent& out_first, GeoExtent& out_second ) const { bool success = false; if ( crossesDateLine() ) { if ( _srs->isGeographic() ) { out_first = GeoExtent( _srs.get(), _xmin, _ymin, 180.0, _ymax ); out_second = GeoExtent( _srs.get(), -180.0, _ymin, _xmax, _ymax ); success = true; } else { GeoExtent latlong_extent = transform( _srs->getGeographicSRS() ); GeoExtent first, second; if ( latlong_extent.splitAcrossDateLine( first, second ) ) { out_first = first.transform( _srs.get() ); out_second = second.transform( _srs.get() ); success = out_first.isValid() && out_second.isValid(); } } } return success; }
void Profile::getIntersectingTiles(const GeoExtent& extent, unsigned localLOD, std::vector<TileKey>& out_intersectingKeys) const { GeoExtent ext = extent; // reproject into the profile's SRS if necessary: if ( !getSRS()->isHorizEquivalentTo( extent.getSRS() ) ) { // localize the extents and clamp them to legal values ext = clampAndTransformExtent( extent ); if ( !ext.isValid() ) return; } if ( ext.crossesAntimeridian() ) { GeoExtent first, second; if (ext.splitAcrossAntimeridian( first, second )) { addIntersectingTiles( first, localLOD, out_intersectingKeys ); addIntersectingTiles( second, localLOD, out_intersectingKeys ); } } else { addIntersectingTiles( ext, localLOD, out_intersectingKeys ); } }
GeoImage* GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent, unsigned int width, unsigned int height) const { GeoExtent destExtent; if (to_extent) { destExtent = *to_extent; } else { destExtent = getExtent().transform(to_srs); } osg::Image* resultImage = 0L; if ( getSRS()->isUserDefined() || to_srs->isUserDefined() ) { // if either of the SRS is a custom projection, we have to do a manual reprojection since // GDAL will not recognize the SRS. resultImage = manualReproject(getImage(), getExtent(), *to_extent, width, height); } else { // otherwise use GDAL. resultImage = reprojectImage(getImage(), getSRS()->getWKT(), getExtent().xMin(), getExtent().yMin(), getExtent().xMax(), getExtent().yMax(), to_srs->getWKT(), destExtent.xMin(), destExtent.yMin(), destExtent.xMax(), destExtent.yMax(), width, height); } return new GeoImage(resultImage, destExtent); }
TileMap* TileMap::create(const std::string& url, const Profile* profile, const DataExtentList& dataExtents, const std::string& format, int tile_width, int tile_height) { const GeoExtent& ex = profile->getExtent(); TileMap* tileMap = new TileMap(); tileMap->setProfileType(profile->getProfileType()); tileMap->setExtents(ex.xMin(), ex.yMin(), ex.xMax(), ex.yMax()); tileMap->setOrigin(ex.xMin(), ex.yMin()); tileMap->_filename = url; tileMap->_srs = getHorizSRSString(profile->getSRS()); tileMap->_vsrs = profile->getSRS()->getVertInitString(); tileMap->_format.setWidth( tile_width ); tileMap->_format.setHeight( tile_height ); profile->getNumTiles( 0, tileMap->_numTilesWide, tileMap->_numTilesHigh ); // format can be a mime-type or an extension: std::string::size_type p = format.find('/'); if ( p == std::string::npos ) { tileMap->_format.setExtension(format); tileMap->_format.setMimeType( Registry::instance()->getMimeTypeForExtension(format) ); } else { tileMap->_format.setMimeType(format); tileMap->_format.setExtension( Registry::instance()->getExtensionForMimeType(format) ); } //Add the data extents tileMap->getDataExtents().insert(tileMap->getDataExtents().end(), dataExtents.begin(), dataExtents.end()); // If we have some data extents specified then make a nicer bounds than the if (!tileMap->getDataExtents().empty()) { // Get the union of all the extents GeoExtent e(tileMap->getDataExtents()[0]); for (unsigned int i = 1; i < tileMap->getDataExtents().size(); i++) { e.expandToInclude(tileMap->getDataExtents()[i]); } // Convert the bounds to the output profile GeoExtent bounds = e.transform(profile->getSRS()); tileMap->setExtents(bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax()); } tileMap->generateTileSets(); tileMap->computeMinMaxLevel(); return tileMap; }
void Profile::addIntersectingTiles(const GeoExtent& key_ext, unsigned localLOD, std::vector<TileKey>& out_intersectingKeys) const { // assume a non-crossing extent here. if ( key_ext.crossesAntimeridian() ) { OE_WARN << "Profile::addIntersectingTiles cannot process date-line cross" << std::endl; return; } int tileMinX, tileMaxX; int tileMinY, tileMaxY; double destTileWidth, destTileHeight; getTileDimensions(localLOD, destTileWidth, destTileHeight); //OE_DEBUG << std::fixed << " Source Tile: " << key.getLevelOfDetail() << " (" << keyWidth << ", " << keyHeight << ")" << std::endl; //OE_DEBUG << std::fixed << " Dest Size: " << destLOD << " (" << destTileWidth << ", " << destTileHeight << ")" << std::endl; double east = key_ext.xMax() - _extent.xMin(); bool xMaxOnTileBoundary = fmod(east, destTileWidth) == 0.0; double south = _extent.yMax() - key_ext.yMin(); bool yMaxOnTileBoundary = fmod(south, destTileHeight) == 0.0; tileMinX = (int)((key_ext.xMin() - _extent.xMin()) / destTileWidth); tileMaxX = (int)(east / destTileWidth) - (xMaxOnTileBoundary ? 1 : 0); tileMinY = (int)((_extent.yMax() - key_ext.yMax()) / destTileHeight); tileMaxY = (int)(south / destTileHeight) - (yMaxOnTileBoundary ? 1 : 0); unsigned int numWide, numHigh; getNumTiles(localLOD, numWide, numHigh); // bail out if the tiles are out of bounds. if ( tileMinX >= (int)numWide || tileMinY >= (int)numHigh || tileMaxX < 0 || tileMaxY < 0 ) { return; } tileMinX = osg::clampBetween(tileMinX, 0, (int)numWide-1); tileMaxX = osg::clampBetween(tileMaxX, 0, (int)numWide-1); tileMinY = osg::clampBetween(tileMinY, 0, (int)numHigh-1); tileMaxY = osg::clampBetween(tileMaxY, 0, (int)numHigh-1); OE_DEBUG << std::fixed << " Dest Tiles: " << tileMinX << "," << tileMinY << " => " << tileMaxX << "," << tileMaxY << std::endl; for (int i = tileMinX; i <= tileMaxX; ++i) { for (int j = tileMinY; j <= tileMaxY; ++j) { //TODO: does not support multi-face destination keys. out_intersectingKeys.push_back( TileKey(localLOD, i, j, this) ); } } }
osgTerrain::ImageLayer* MapEngine::createImageLayer(Map* map, MapLayer* layer, const TileKey* key, ProgressCallback* progress) { Threading::ScopedReadLock lock( map->getMapDataMutex() ); osg::ref_ptr< GeoImage > geoImage; //If the key is valid, try to get the image from the MapLayer if (layer->isKeyValid( key ) ) { geoImage = layer->createImage(key, progress); } else { //If the key is not valid, simply make a transparent tile geoImage = new GeoImage(ImageUtils::createEmptyImage(), key->getGeoExtent()); } if (geoImage.valid()) { bool isProjected = map->getCoordinateSystemType() == Map::CSTYPE_PROJECTED; bool isPlateCarre = isProjected && map->getProfile()->getSRS()->isGeographic(); bool isGeocentric = !isProjected; osg::ref_ptr<GeoLocator> imgLocator; // Use a special locator for mercator images (instead of reprojecting) if (map->getProfile()->getSRS()->isGeographic() && geoImage->getSRS()->isMercator() && layer->useMercatorFastPath() == true ) { GeoExtent gx = geoImage->getExtent().transform( geoImage->getExtent().getSRS()->getGeographicSRS() ); imgLocator = key->getProfile()->getSRS()->createLocator( gx.xMin(), gx.yMin(), gx.xMax(), gx.yMax() ); imgLocator = new MercatorLocator( *imgLocator.get(), geoImage->getExtent() ); } else { const GeoExtent& gx = geoImage->getExtent(); imgLocator = GeoLocator::createForKey( key, map ); } if ( isGeocentric ) imgLocator->setCoordinateSystemType( osgTerrain::Locator::GEOCENTRIC ); //osgTerrain::ImageLayer* imgLayer = new osgTerrain::ImageLayer( geoImage->getImage() ); TransparentLayer* imgLayer = new TransparentLayer(geoImage->getImage(), layer); imgLayer->setLocator( imgLocator.get() ); imgLayer->setLevelOfDetail( key->getLevelOfDetail() ); imgLayer->setMinFilter( layer->getMinFilter().value()); imgLayer->setMagFilter( layer->getMagFilter().value()); return imgLayer; } return NULL; }
GeoExtent GeoExtent::intersectionSameSRS( const GeoExtent& rhs ) const { Bounds b( osg::maximum( xMin(), rhs.xMin() ), osg::maximum( yMin(), rhs.yMin() ), osg::minimum( xMax(), rhs.xMax() ), osg::minimum( yMax(), rhs.yMax() ) ); return b.width() > 0 && b.height() > 0 ? GeoExtent( getSRS(), b ) : GeoExtent::INVALID; }
bool GeoExtent::intersects( const GeoExtent& rhs ) const { bool valid = isValid(); if ( !valid ) return false; bool exclusive = _xmin > rhs.xMax() || _xmax < rhs.xMin() || _ymin > rhs.yMax() || _ymax < rhs.yMin(); return !exclusive; }
/** * Gets all the features that intersect the extent */ void getFeatures(const GeoExtent& extent, FeatureList& features) { GeoExtent localExtent = extent.transform( _featureSource->getFeatureProfile()->getSRS() ); Query query; query.bounds() = localExtent.bounds(); if (localExtent.intersects( _featureSource->getFeatureProfile()->getExtent())) { osg::ref_ptr< FeatureCursor > cursor = _featureSource->createFeatureCursor( query ); if (cursor) { cursor->fill( features ); } } }
bool GeoLocator::createScaleBiasMatrix(const GeoExtent& window, osg::Matrixf& out) const { float scalex = window.width() / _dataExtent.width(); float scaley = window.height() / _dataExtent.height(); float biasx = (window.xMin()-_dataExtent.xMin()) / _dataExtent.width(); float biasy = (window.yMin()-_dataExtent.yMin()) / _dataExtent.height(); out(0,0) = scalex; out(1,1) = scaley; out(3,0) = biasx; out(3,1) = biasy; return true; }
bool GeoExtent::operator == ( const GeoExtent& rhs ) const { if ( !isValid() && !rhs.isValid() ) return true; else return isValid() && rhs.isValid() && _xmin == rhs._xmin && _ymin == rhs._ymin && _xmax == rhs._xmax && _ymax == rhs._ymax && _srs.valid() && rhs._srs.valid() && _srs->isEquivalentTo( rhs._srs.get() ); }
GeoImage GeoImage::crop( const GeoExtent& extent, bool exact, unsigned int width, unsigned int height ) const { //Check for equivalence if ( extent.getSRS()->isEquivalentTo( getSRS() ) ) { //If we want an exact crop or they want to specify the output size of the image, use GDAL if (exact || width != 0 || height != 0 ) { OE_DEBUG << "[osgEarth::GeoImage::crop] Performing exact crop" << std::endl; //Suggest an output image size if (width == 0 || height == 0) { double xRes = (getExtent().xMax() - getExtent().xMin()) / (double)_image->s(); double yRes = (getExtent().yMax() - getExtent().yMin()) / (double)_image->t(); width = osg::maximum(1u, (unsigned int)((extent.xMax() - extent.xMin()) / xRes)); height = osg::maximum(1u, (unsigned int)((extent.yMax() - extent.yMin()) / yRes)); OE_DEBUG << "[osgEarth::GeoImage::crop] Computed output image size " << width << "x" << height << std::endl; } //Note: Passing in the current SRS simply forces GDAL to not do any warping return reproject( getSRS(), &extent, width, height); } else { OE_DEBUG << "[osgEarth::GeoImage::crop] Performing non-exact crop " << std::endl; //If an exact crop is not desired, we can use the faster image cropping code that does no resampling. double destXMin = extent.xMin(); double destYMin = extent.yMin(); double destXMax = extent.xMax(); double destYMax = extent.yMax(); osg::Image* new_image = ImageUtils::cropImage( _image.get(), _extent.xMin(), _extent.yMin(), _extent.xMax(), _extent.yMax(), destXMin, destYMin, destXMax, destYMax ); //The destination extents may be different than the input extents due to not being able to crop along pixel boundaries. return new_image? GeoImage( new_image, GeoExtent( getSRS(), destXMin, destYMin, destXMax, destYMax ) ) : GeoImage::INVALID; } } else { //TODO: just reproject the image before cropping OE_NOTICE << "[osgEarth::GeoImage::crop] Cropping extent does not have equivalent SpatialReference" << std::endl; return GeoImage::INVALID; } }
void MPTerrainEngineNode::invalidateRegion(const GeoExtent& extent, unsigned minLevel, unsigned maxLevel) { if (_terrainOptions.incrementalUpdate() == true && _liveTiles.valid()) { GeoExtent extentLocal = extent; if ( !extent.getSRS()->isEquivalentTo(this->getMap()->getSRS()) ) { extent.transform(this->getMap()->getSRS(), extentLocal); } _liveTiles->setDirty(extentLocal, minLevel, maxLevel); } }
GeoExtent Profile::clampAndTransformExtent( const GeoExtent& input, bool* out_clamped ) const { if ( out_clamped ) *out_clamped = false; // do the clamping in LAT/LONG. const SpatialReference* geo_srs = getSRS()->getGeographicSRS(); // get the input in lat/long: GeoExtent gcs_input = input.getSRS()->isGeographic()? input : input.transform( geo_srs ); // bail out on a bad transform: if ( !gcs_input.isValid() ) return GeoExtent::INVALID; // bail out if the extent's do not intersect at all: if ( !gcs_input.intersects(_latlong_extent, false) ) return GeoExtent::INVALID; // clamp it to the profile's extents: GeoExtent clamped_gcs_input = GeoExtent( gcs_input.getSRS(), osg::clampBetween( gcs_input.xMin(), _latlong_extent.xMin(), _latlong_extent.xMax() ), osg::clampBetween( gcs_input.yMin(), _latlong_extent.yMin(), _latlong_extent.yMax() ), osg::clampBetween( gcs_input.xMax(), _latlong_extent.xMin(), _latlong_extent.xMax() ), osg::clampBetween( gcs_input.yMax(), _latlong_extent.yMin(), _latlong_extent.yMax() ) ); if ( out_clamped ) *out_clamped = (clamped_gcs_input != gcs_input); // finally, transform the clamped extent into this profile's SRS and return it. GeoExtent result = clamped_gcs_input.getSRS()->isEquivalentTo( this->getSRS() )? clamped_gcs_input : clamped_gcs_input.transform( this->getSRS() ); if (result.isValid()) { OE_DEBUG << LC << "clamp&xform: input=" << input.toString() << ", output=" << result.toString() << std::endl; } return result; }
osg::Node* SingleKeyNodeFactory::createTile(TileModel* model, bool setupChildrenIfNecessary) { // compile the model into a node: TileNode* tileNode = _modelCompiler->compile( model, _frame ); // see if this tile might have children. bool prepareForChildren = setupChildrenIfNecessary && model->_tileKey.getLOD() < *_options.maxLOD(); osg::Node* result = 0L; if ( prepareForChildren ) { //Compute the min range based on the 2D size of the tile osg::BoundingSphere bs = tileNode->getBound(); GeoExtent extent = model->_tileKey.getExtent(); GeoPoint lowerLeft(extent.getSRS(), extent.xMin(), extent.yMin(), 0.0, ALTMODE_ABSOLUTE); GeoPoint upperRight(extent.getSRS(), extent.xMax(), extent.yMax(), 0.0, ALTMODE_ABSOLUTE); osg::Vec3d ll, ur; lowerLeft.toWorld( ll ); upperRight.toWorld( ur ); double radius = (ur - ll).length() / 2.0; float minRange = (float)(radius * _options.minTileRangeFactor().value()); TilePagedLOD* plod = new TilePagedLOD( _engineUID, _liveTiles, _deadTiles ); plod->setCenter ( bs.center() ); plod->addChild ( tileNode ); plod->setRange ( 0, minRange, FLT_MAX ); plod->setFileName( 1, Stringify() << tileNode->getKey().str() << "." << _engineUID << ".osgearth_engine_mp_tile" ); plod->setRange ( 1, 0, minRange ); #if USE_FILELOCATIONCALLBACK osgDB::Options* options = Registry::instance()->cloneOrCreateOptions(); options->setFileLocationCallback( new FileLocationCallback() ); plod->setDatabaseOptions( options ); #endif result = plod; // this one rejects back-facing tiles: if ( _frame.getMapInfo().isGeocentric() && _options.clusterCulling() == true ) { osg::HeightField* hf = model->_elevationData.getHeightField(); result->addCullCallback( HeightFieldUtils::createClusterCullingCallback( hf, tileNode->getKey().getProfile()->getSRS()->getEllipsoid(), *_options.verticalScale() ) ); } } else { result = tileNode; } return result; }
osg::BoundingSphered FeatureModelGraph::getBoundInWorldCoords( const GeoExtent& extent ) const { osg::Vec3d center, corner; GeoExtent workingExtent; if ( extent.getSRS()->isEquivalentTo( _usableMapExtent.getSRS() ) ) { workingExtent = extent; } else { workingExtent = extent.transform( _usableMapExtent.getSRS() ); // safe. } workingExtent.getCentroid( center.x(), center.y() ); corner.x() = workingExtent.xMin(); corner.y() = workingExtent.yMin(); if ( _session->getMapInfo().isGeocentric() ) { workingExtent.getSRS()->transformToECEF( center, center ); workingExtent.getSRS()->transformToECEF( corner, corner ); } return osg::BoundingSphered( center, (center-corner).length() ); }
osg::HeightField* HeightFieldUtils::createReferenceHeightField(const GeoExtent& ex, unsigned numCols, unsigned numRows, bool expressAsHAE) { osg::HeightField* hf = new osg::HeightField(); hf->allocate( numCols, numRows ); hf->setOrigin( osg::Vec3d( ex.xMin(), ex.yMin(), 0.0 ) ); hf->setXInterval( (ex.xMax() - ex.xMin())/(double)(numCols-1) ); hf->setYInterval( (ex.yMax() - ex.yMin())/(double)(numRows-1) ); const VerticalDatum* vdatum = ex.isValid() ? ex.getSRS()->getVerticalDatum() : 0L; if ( vdatum && expressAsHAE ) { // need the lat/long extent for geoid queries: GeoExtent geodeticExtent = ex.getSRS()->isGeographic() ? ex : ex.transform( ex.getSRS()->getGeographicSRS() ); double latMin = geodeticExtent.yMin(); double lonMin = geodeticExtent.xMin(); double lonInterval = geodeticExtent.width() / (double)(numCols-1); double latInterval = geodeticExtent.height() / (double)(numRows-1); for( unsigned r=0; r<numRows; ++r ) { double lat = latMin + latInterval*(double)r; for( unsigned c=0; c<numCols; ++c ) { double lon = lonMin + lonInterval*(double)c; double offset = vdatum->msl2hae(lat, lon, 0.0); hf->setHeight( c, r, offset ); } } } else { for(unsigned int i=0; i<hf->getHeightList().size(); i++ ) { hf->getHeightList()[i] = 0.0; } } hf->setBorderWidth( 0 ); return hf; }
GeoLocator::GeoLocator( const osgTerrain::Locator& prototype, const GeoExtent& dataExtent, const GeoExtent& displayExtent ) : osgTerrain::Locator( prototype ), _dataExtent( dataExtent ), _inverseCalculated(false) { // assume they are the same SRS _x0 = osg::clampBetween( (displayExtent.xMin()-dataExtent.xMin())/dataExtent.width(), 0.0, 1.0 ); _x1 = osg::clampBetween( (displayExtent.xMax()-dataExtent.xMin())/dataExtent.width(), 0.0, 1.0 ); _y0 = osg::clampBetween( (displayExtent.yMin()-dataExtent.yMin())/dataExtent.height(), 0.0, 1.0 ); _y1 = osg::clampBetween( (displayExtent.yMax()-dataExtent.yMin())/dataExtent.height(), 0.0, 1.0 ); }
osg::Node* SerialKeyNodeFactory::createTile(TileModel* model, bool tileHasRealData) { // compile the model into a node: TileNode* tileNode = _modelCompiler->compile( model ); // see if this tile might have children. bool prepareForChildren = (tileHasRealData || (_options.minLOD().isSet() && model->_tileKey.getLOD() < *_options.minLOD())) && model->_tileKey.getLOD() < *_options.maxLOD(); osg::Node* result = 0L; if ( prepareForChildren ) { //Compute the min range based on the 2D size of the tile osg::BoundingSphere bs = tileNode->getBound(); GeoExtent extent = model->_tileKey.getExtent(); GeoPoint lowerLeft(extent.getSRS(), extent.xMin(), extent.yMin(), 0.0, ALTMODE_ABSOLUTE); GeoPoint upperRight(extent.getSRS(), extent.xMax(), extent.yMax(), 0.0, ALTMODE_ABSOLUTE); osg::Vec3d ll, ur; lowerLeft.toWorld( ll ); upperRight.toWorld( ur ); double radius = (ur - ll).length() / 2.0; float minRange = (float)(radius * _options.minTileRangeFactor().value()); osgDB::Options* dbOptions = Registry::instance()->cloneOrCreateOptions(); TileGroup* plod = new TileGroup(tileNode, _engineUID, _liveTiles.get(), _deadTiles.get(), dbOptions); plod->setSubtileRange( minRange ); #if USE_FILELOCATIONCALLBACK dbOptions->setFileLocationCallback( new FileLocationCallback() ); #endif result = plod; } else { result = tileNode; } // this one rejects back-facing tiles: if ( _mapInfo.isGeocentric() && _options.clusterCulling() == true ) { osg::HeightField* hf = model->_elevationData.getHeightField(); result->addCullCallback( HeightFieldUtils::createClusterCullingCallback( hf, tileNode->getKey().getProfile()->getSRS()->getEllipsoid(), *_options.verticalScale() ) ); } return result; }
bool TerrainLayer::mayHaveDataInExtent(const GeoExtent& ex) const { if (!ex.isValid()) { // bad extent; no data return false; } const DataExtentList& de = getDataExtents(); if (de.empty()) { // not enough info, assume yes return true; } // Get extent in local profile: GeoExtent localExtent = ex; if (getProfile() && getProfile()->getSRS()->isHorizEquivalentTo(ex.getSRS())) { localExtent = getProfile()->clampAndTransformExtent(ex); } // Check union: if (getDataExtentsUnion().intersects(localExtent)) { // possible yes return true; } // Check each extent in turn: for (DataExtentList::const_iterator i = de.begin(); i != de.end(); ++i) { if (i->intersects(localExtent)) { // possible yes return true; } } // definite no. return false; }
void TileIndex::getFiles(const osgEarth::GeoExtent& extent, std::vector< std::string >& files) { files.clear(); osgEarth::Symbology::Query query; GeoExtent transformed = extent.transform( _features->getFeatureProfile()->getSRS() ); query.bounds() = transformed.bounds(); osg::ref_ptr< osgEarth::Features::FeatureCursor> cursor = _features->createFeatureCursor( query, 0L ); while (cursor->hasMore()) { osg::ref_ptr< osgEarth::Features::Feature> feature = cursor->nextFeature(); if (feature.valid()) { std::string location = getFullPath(_filename, feature->getString("location")); files.push_back( location ); } } }
osg::BoundingSphered FeatureModelGraph::getBoundInWorldCoords(const GeoExtent& extent, const MapFrame* mapf ) const { osg::Vec3d center, corner; GeoExtent workingExtent; if ( !extent.isValid() ) { return osg::BoundingSphered(); } if ( extent.getSRS()->isEquivalentTo( _usableMapExtent.getSRS() ) ) { workingExtent = extent; } else { workingExtent = extent.transform( _usableMapExtent.getSRS() ); // safe. } workingExtent.getCentroid( center.x(), center.y() ); double centerZ = 0.0; if ( mapf ) { // Use an appropriate resolution for this extents width double resolution = workingExtent.width(); ElevationQuery query( *mapf ); GeoPoint p( mapf->getProfile()->getSRS(), center, ALTMODE_ABSOLUTE ); query.getElevation( p, center.z(), resolution ); centerZ = center.z(); } corner.x() = workingExtent.xMin(); corner.y() = workingExtent.yMin(); corner.z() = 0; if ( _session->getMapInfo().isGeocentric() ) { workingExtent.getSRS()->transformToECEF( center, center ); workingExtent.getSRS()->transformToECEF( corner, corner ); } return osg::BoundingSphered( center, (center-corner).length() ); }