bool LocalizedNode::setPosition( const GeoPoint& pos ) { if ( _initComplete ) { if ( getMapNode() ) { // first transform the point to the map's SRS: const SpatialReference* mapSRS = getMapNode()->getMapSRS(); GeoPoint mapPos = mapSRS ? pos.transform(mapSRS) : pos; if ( !mapPos.isValid() ) return false; _mapPosition = mapPos; } else { _mapPosition = pos; } // make sure the node is set up for auto-z-update if necessary: configureForAltitudeMode( _mapPosition.altitudeMode() ); // update the node. return updateTransform( _mapPosition ); } else { _mapPosition = pos; return true; } }
bool OrthoNode::setPosition( const GeoPoint& position ) { MapNode* mapNode = getMapNode(); if ( mapNode ) { // first transform the point to the map's SRS: const SpatialReference* mapSRS = mapNode->getMapSRS(); GeoPoint mapPos = mapSRS ? position.transform(mapSRS) : position; if ( !mapPos.isValid() ) return false; _mapPosition = mapPos; } else { _mapPosition = position; } // make sure the node is set up for auto-z-update if necessary: configureForAltitudeMode( _mapPosition.altitudeMode() ); // and update the node. if ( !updateTransforms(_mapPosition) ) return false; return true; }
bool LocalizedNode::setPosition( const GeoPoint& pos ) { if ( _mapSRS.valid() ) { // first transform the point to the map's SRS: GeoPoint mapPos = _mapSRS.get() ? pos.transform(_mapSRS.get()) : pos; if ( !mapPos.isValid() ) return false; _mapPosition = mapPos; } else { _mapPosition = pos; } // make sure the node is set up for auto-z-update if necessary: configureForAltitudeMode( _mapPosition.altitudeMode() ); // update the node. if ( !updateTransforms( _mapPosition ) ) return false; return true; }
bool TileSource::hasDataAt( const GeoPoint& location, bool exact) const { // If the location is invalid then return false if (!location.isValid()) return false; // If no data extents are provided, just return true if (_dataExtents.size() == 0) return true; if (!exact) { return getDataExtentsUnion().contains(location); } for (DataExtentList::const_iterator itr = _dataExtents.begin(); itr != _dataExtents.end(); ++itr) { if (itr->contains( location ) ) { return true; } } return false; }
bool MapInfo::toWorldPoint( const GeoPoint& input, osg::Vec3d& output ) const { return input.isValid() ? input.getSRS()->transformToWorld(input.vec3d(), output) : false; }
bool MapInfo::toWorldPoint( const GeoPoint& input, osg::Vec3d& output ) const { if (!input.isValid()) return false; //Transform the incoming point to the map's SRS GeoPoint mapPoint; toMapPoint(input, mapPoint ); return mapPoint.toWorld( output ); }
bool GeoPoint::operator == ( const GeoPoint& rhs ) const { return isValid() && rhs.isValid() && SpatialReference::equivalent( getSRS(), rhs.getSRS() ) && getDim() == rhs.getDim() && x() == rhs.x() && (getDim() < 2 || y() == rhs.y()) && (getDim() < 3 || z() == rhs.z()); }
bool OrthoNode::setPosition( const GeoPoint& position ) { MapNode* mapNode = getMapNode(); if ( mapNode ) { // first transform the point to the map's SRS: const SpatialReference* mapSRS = mapNode->getMapSRS(); //$$$注释 //GeoPoint mapPos = mapSRS ? position.transform(mapSRS) : position; //if ( !mapPos.isValid() ) // return false; //_mapPosition = mapPos; //$$$修改 if ( mapSRS && position.isValid() )//position原来SRS信息不为空 { position.transform( mapSRS ); _mapPosition = position; } else if ( mapSRS ) { _mapPosition = GeoPoint( mapSRS, position.x(), position.y(), position.z() );//position原来SRS信息为空 } else { _mapPosition = position; } } else { _mapPosition = position; } // make sure the node is set up for auto-z-update if necessary: configureForAltitudeMode( _mapPosition.altitudeMode() ); // and update the node. if ( !updateTransforms(_mapPosition) ) return false; return true; }
void GLSkyNode::onSetDateTime() { if ( !getSunLight() || !_profile.valid() ) return; const DateTime& dt = getDateTime(); osg::Vec3d sunPosECEF = getEphemeris()->getSunPositionECEF( dt ); if ( _profile->getSRS()->isGeographic() ) { sunPosECEF.normalize(); getSunLight()->setPosition( osg::Vec4(sunPosECEF, 0.0) ); } else { // pull the ref point: GeoPoint refpoint = getReferencePoint(); if ( !refpoint.isValid() ) { // not found; use the center of the profile: _profile->getExtent().getCentroid(refpoint); } // convert to lat/long: GeoPoint refLatLong; refpoint.transform(_profile->getSRS()->getGeographicSRS(), refLatLong); // Matrix to convert the ECEF sun position to the local tangent plane // centered on our reference point: osg::Matrixd world2local; refLatLong.createWorldToLocal(world2local); // convert the sun position: osg::Vec3d sunPosLocal = sunPosECEF * world2local; sunPosLocal.normalize(); getSunLight()->setPosition( osg::Vec4(sunPosLocal, 0.0) ); } }
bool LocalizedNode::updateTransform( const GeoPoint& p, osg::Node* patch ) { if ( p.isValid() ) { GeoPoint absPos(p); if ( !makeAbsolute(absPos, patch) ) return false; OE_DEBUG << LC << "Update transforms for position: " << absPos.x() << ", " << absPos.y() << ", " << absPos.z() << std::endl; osg::Matrixd local2world; absPos.createLocalToWorld( local2world ); // apply the local offsets local2world.preMult( osg::Matrix::translate(_localOffset) ); getTransform()->setMatrix( osg::Matrix::scale (_scale) * osg::Matrix::rotate(_localRotation) * local2world ); } else { osg::Vec3d absPos = p.vec3d() + _localOffset; getTransform()->setMatrix( osg::Matrix::scale (_scale) * osg::Matrix::rotate (_localRotation) * osg::Matrix::translate(absPos) ); } dirtyBound(); return true; }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, /* abs */ double& out_elevation, double desiredResolution, double* out_actualResolution) { // assertion. if ( !point.isAbsolute() ) { OE_WARN << LC << "Assertion failure; input must be absolute" << std::endl; return false; } osg::Timer_t begin = osg::Timer::instance()->tick(); // first try the terrain patches. if ( _patchLayers.size() > 0 ) { osgUtil::IntersectionVisitor iv; for(std::vector<ModelLayer*>::iterator i = _patchLayers.begin(); i != _patchLayers.end(); ++i) { // find the scene graph for this layer: osg::Node* node = (*i)->getSceneGraph( _mapf.getUID() ); if ( node ) { // configure for intersection: osg::Vec3d surface; point.toWorld( surface ); // trivial bounds check: if ( node->getBound().contains(surface) ) { osg::Vec3d nvector; point.createWorldUpVector(nvector); osg::Vec3d start( surface + nvector*5e5 ); osg::Vec3d end ( surface - nvector*5e5 ); // first time through, set up the intersector on demand if ( !_patchLayersLSI.valid() ) { _patchLayersLSI = new DPLineSegmentIntersector(start, end); _patchLayersLSI->setIntersectionLimit( _patchLayersLSI->LIMIT_NEAREST ); } else { _patchLayersLSI->reset(); _patchLayersLSI->setStart( start ); _patchLayersLSI->setEnd ( end ); } // try it. iv.setIntersector( _patchLayersLSI.get() ); node->accept( iv ); // check for a result!! if ( _patchLayersLSI->containsIntersections() ) { osg::Vec3d isect = _patchLayersLSI->getIntersections().begin()->getWorldIntersectPoint(); // transform back to input SRS: GeoPoint output; output.fromWorld( point.getSRS(), isect ); out_elevation = output.z(); if ( out_actualResolution ) *out_actualResolution = 0.0; return true; } } else { //OE_INFO << LC << "Trivial rejection (bounds check)" << std::endl; } } } } if ( _mapf.elevationLayers().empty() ) { // this means there are no heightfields. out_elevation = 0.0; return true; } // tile size (resolution of elevation tiles) unsigned tileSize = std::max(_mapf.getMapOptions().elevationTileSize().get(), 2u); //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << LC << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isHorizEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } bool result = false; while (!result) { GeoHeightField geoHF; TileCache::Record record; // Try to get the hf from the cache if ( _cache.get( key, record ) ) { geoHF = record.value(); } else { // Create it osg::ref_ptr<osg::HeightField> hf = new osg::HeightField(); hf->allocate( tileSize, tileSize ); // Initialize the heightfield to nodata for (unsigned int i = 0; i < hf->getFloatArray()->size(); i++) { hf->getFloatArray()->at( i ) = NO_DATA_VALUE; } if (_mapf.populateHeightField(hf, key, false)) { geoHF = GeoHeightField( hf.get(), key.getExtent() ); _cache.insert( key, geoHF ); } } if (geoHF.valid()) { float elevation = 0.0f; result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation); if (result && elevation != NO_DATA_VALUE) { // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = geoHF.getXInterval(); out_elevation = (double)elevation; break; } else { result = false; } } if (!result) { key = key.createParentKey(); if (!key.valid()) { break; } } } osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( begin, end ); return result; }
bool MapInfo::toMapPoint( const GeoPoint& input, GeoPoint& output ) const { return input.isValid() ? input.transform(_profile->getSRS(), output) : false; }
bool LocalizedNode::updateTransforms( const GeoPoint& p, osg::Node* patch ) { if ( p.isValid() ) { GeoPoint absPos(p); if ( !makeAbsolute(absPos, patch) ) return false; OE_DEBUG << LC << "Update transforms for position: " << absPos.x() << ", " << absPos.y() << ", " << absPos.z() << std::endl; osg::Matrixd local2world; absPos.createLocalToWorld( local2world ); // apply the local offsets local2world.preMult( osg::Matrix::translate(_localOffset) ); if ( _autoTransform ) { static_cast<osg::AutoTransform*>(_xform.get())->setPosition( local2world.getTrans() ); static_cast<osg::AutoTransform*>(_xform.get())->setScale( _scale ); static_cast<osg::AutoTransform*>(_xform.get())->setRotation( _localRotation ); } else { static_cast<osg::MatrixTransform*>(_xform.get())->setMatrix( osg::Matrix::scale(_scale) * osg::Matrix::rotate(_localRotation) * local2world ); } CullNodeByHorizon* culler = dynamic_cast<CullNodeByHorizon*>(_xform->getCullCallback()); if ( culler ) culler->_world = local2world.getTrans(); } else { osg::Vec3d absPos = p.vec3d() + _localOffset; if ( _autoTransform ) { static_cast<osg::AutoTransform*>(_xform.get())->setPosition( absPos ); static_cast<osg::AutoTransform*>(_xform.get())->setScale( _scale ); static_cast<osg::AutoTransform*>(_xform.get())->setRotation( _localRotation ); } else { static_cast<osg::MatrixTransform*>(_xform.get())->setMatrix( osg::Matrix::scale(_scale) * osg::Matrix::rotate(_localRotation) * osg::Matrix::translate(absPos) ); } } dirtyBound(); return true; }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, double& out_elevation, double desiredResolution, double* out_actualResolution) { osg::Timer_t start = osg::Timer::instance()->tick(); if ( _maxDataLevel == 0 || _tileSize == 0 ) { // this means there are no heightfields. out_elevation = 0.0; return true; } //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, _tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } osg::ref_ptr<osg::HeightField> tile; // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } // Check the tile cache. Note that the TileSource already likely has a MemCache // attached to it. We employ a secondary cache here for a couple reasons. One, this // cache will store not only the heightfield, but also the tesselated tile in the event // that we're using GEOMETRIC mode. Second, since the call the getHeightField can // fallback on a lower resolution, this cache will hold the final resolution heightfield // instead of trying to fetch the higher resolution one each item. TileCache::Record record; if ( _tileCache.get(key, record) ) { tile = record.value().get(); } // if we didn't find it, build it. if ( !tile.valid() ) { // generate the heightfield corresponding to the tile key, automatically falling back // on lower resolution if necessary: _mapf.getHeightField( key, true, tile, 0L ); // bail out if we could not make a heightfield a all. if ( !tile.valid() ) { OE_WARN << LC << "Unable to create heightfield for key " << key.str() << std::endl; return false; } _tileCache.insert(key, tile.get()); } OE_DEBUG << LC << "LRU Cache, hit ratio = " << _tileCache.getStats()._hitRatio << std::endl; // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = (double)tile->getXInterval(); bool result = true; const GeoExtent& extent = key.getExtent(); double xInterval = extent.width() / (double)(tile->getNumColumns()-1); double yInterval = extent.height() / (double)(tile->getNumRows()-1); out_elevation = (double) HeightFieldUtils::getHeightAtLocation( tile.get(), mapPoint.x(), mapPoint.y(), extent.xMin(), extent.yMin(), xInterval, yInterval, _mapf.getMapInfo().getElevationInterpolation() ); osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( start, end ); return result; }
bool MGRSFormatter::transform( const GeoPoint& input, MGRSCoord& out ) const { if ( !input.isValid() ) return false; // convert to lat/long if necessary: GeoPoint inputGeo = input; if ( !inputGeo.makeGeographic() ) return false; unsigned zone; char gzd; unsigned x=0, y=0; char sqid[3]; std::string space; if ( _options & USE_SPACES ) space = " "; sqid[0] = '?'; sqid[1] = '?'; sqid[2] = 0; double latDeg = inputGeo.y(); double lonDeg = inputGeo.x(); if ( latDeg >= 84.0 || latDeg <= -80.0 ) // polar projection { bool isNorth = latDeg > 0.0; zone = 0; gzd = isNorth ? (lonDeg < 0.0 ? 'Y' : 'Z') : (lonDeg < 0.0? 'A' : 'B'); osg::ref_ptr<const SpatialReference> ups = const_cast<MGRSFormatter*>(this)->_srsCache[ s_polarZoneSpecs[isNorth?0:1] ]; if (!ups.valid()) ups = SpatialReference::create( s_polarZoneSpecs[isNorth?0:1] ); if ( !ups.valid() ) { OE_WARN << LC << "Failed to create UPS SRS" << std::endl; return false; } osg::Vec3d upsCoord; if ( _refSRS->transform(osg::Vec3d(lonDeg,latDeg,0), ups.get(), upsCoord) == false ) { OE_WARN << LC << "Failed to transform lat/long to UPS" << std::endl; return false; } int sqXOffset = upsCoord.x() >= 0.0 ? (int)floor(upsCoord.x()/100000.0) : -(int)floor(1.0-(upsCoord.x()/100000.0)); int sqYOffset = upsCoord.y() >= 0.0 ? (int)floor(upsCoord.y()/100000.0) : -(int)floor(1.0-(upsCoord.y()/100000.0)); int alphaOffset = isNorth ? 7 : 12; sqid[0] = UPS_COL_ALPHABET[ (UPS_COL_ALPHABET_SIZE+sqXOffset) % UPS_COL_ALPHABET_SIZE ]; sqid[1] = UPS_ROW_ALPHABET[alphaOffset + sqYOffset]; x = (unsigned)(upsCoord.x() - (100000.0*(double)sqXOffset)); y = (unsigned)(upsCoord.y() - (100000.0*(double)sqYOffset)); } else // UTM { // figure out the grid zone designator unsigned gzdIndex = ((unsigned)(latDeg+80.0))/8; gzd = GZD_ALPHABET[gzdIndex]; // figure out the UTM zone: zone = (unsigned)floor((lonDeg+180.0)/6.0); // [0..59] bool north = latDeg >= 0.0; // convert the input coordinates to UTM: // yes, always use +north so we get Y relative to equator // using an SRS cache speed things up a lot.. osg::ref_ptr<const SpatialReference>& utm = const_cast<MGRSFormatter*>(this)->_srsCache[s_lateralZoneSpecs[zone]]; if ( !utm.valid() ) utm = SpatialReference::create( s_lateralZoneSpecs[zone] ); osg::Vec3d utmCoord; if ( _refSRS->transform( osg::Vec3d(lonDeg,latDeg,0), utm.get(), utmCoord) == false ) { OE_WARN << LC << "Error transforming lat/long into UTM" << std::endl; return false; } // the alphabet set: unsigned set = zone % 6; // [0..5] // find the horizontal SQID offset (100KM increments) from the central meridian: unsigned xSetOffset = 8 * (set % 3); double xMeridianOffset = utmCoord.x() - 500000.0; int sqMeridianOffset = xMeridianOffset >= 0.0 ? (int)floor(xMeridianOffset/100000.0) : -(int)floor(1.0-(xMeridianOffset/100000.0)); unsigned indexOffset = (4 + sqMeridianOffset); sqid[0] = UTM_COL_ALPHABET[xSetOffset + indexOffset]; double xWest = 500000.0 + (100000.0*(double)sqMeridianOffset); x = (unsigned)(utmCoord.x() - xWest); // find the vertical SQID offset (100KM increments) from the equator: unsigned ySetOffset = 5 * (zone % 2); //(set % 2); int sqEquatorOffset = (int)floor(utmCoord.y()/100000.0); int absOffset = ySetOffset + sqEquatorOffset + (10 * UTM_ROW_ALPHABET_SIZE); if ( _useAL ) absOffset += 10; sqid[1] = UTM_ROW_ALPHABET[absOffset % UTM_ROW_ALPHABET_SIZE]; y = (unsigned)(utmCoord.y() - (100000.0*(double)sqEquatorOffset)); } if ( (unsigned)_precision > PRECISION_1M ) { x /= (unsigned)_precision; y /= (unsigned)_precision; } out.gzd = Stringify() << (zone+1) << gzd; out.sqid = sqid; out.x = x; out.y = y; return true; }
bool GeoTransform::setPosition(const GeoPoint& position) { if ( !position.isValid() ) return false; _position = position; // relative Z or reprojection require a terrain: osg::ref_ptr<Terrain> terrain; _terrain.lock(terrain); // relative Z requires a terrain: if (position.altitudeMode() == ALTMODE_RELATIVE && !terrain.valid()) { OE_TEST << LC << "setPosition failed condition 1\n"; return false; } GeoPoint p; // transform into terrain SRS if neccesary: if (terrain.valid() && !terrain->getSRS()->isEquivalentTo(position.getSRS())) p = position.transform(terrain->getSRS()); else p = position; // bail if the transformation failed: if ( !p.isValid() ) { OE_TEST << LC << "setPosition failed condition 2\n"; return false; } // convert to absolute height: if ( !p.makeAbsolute(_terrain.get()) ) { OE_TEST << LC << "setPosition failed condition 3\n"; return false; } // assemble the matrix: osg::Matrixd local2world; p.createLocalToWorld( local2world ); this->setMatrix( local2world ); // install auto-recompute? if (_autoRecompute && _position.altitudeMode() == ALTMODE_RELATIVE && !_autoRecomputeReady) { // by using the adapter, there's no need to remove // the callback then this object destructs. terrain->addTerrainCallback( new TerrainCallbackAdapter<GeoTransform>(this) ); _autoRecomputeReady = true; } return true; }
bool OGR_SpatialReference::transformInPlace( GeoPoint& input ) const { if ( !handle || !input.isValid() ) { osgGIS::notify( osg::WARN ) << "Spatial reference or input point is invalid" << std::endl; return false; } OGR_SpatialReference* input_sr = (OGR_SpatialReference*)input.getSRS(); if ( !input_sr ) { osgGIS::notify( osg::WARN ) << "SpatialReference: input point has no SRS" << std::endl; return false; } // first check whether the input point is geocentric - and if so, pre-convert it to geographic: if ( input_sr->isGeocentric() ) { input.set( input * input_sr->getInverseReferenceFrame() ); osg::Vec3d temp = input_sr->getEllipsoid().geocentricToLatLong( input ); input = GeoPoint( temp, input_sr->getGeographicSRS() ); input_sr = static_cast<OGR_SpatialReference*>( input.getSRS() ); } osg::Vec3d input_vec = input; bool crs_equiv = false; bool mat_equiv = false; testEquivalence( input_sr, /*out*/crs_equiv, /*out*/mat_equiv ); // pull it out of its source frame: if ( !mat_equiv ) { input.set( input * input_sr->inv_ref_frame ); } bool result = false; if ( !crs_equiv ) { OGR_SCOPE_LOCK(); //TODO: some kind of per-thread cache void* xform_handle = OCTNewCoordinateTransformation( input_sr->handle, this->handle ); if ( !xform_handle ) { osgGIS::notify( osg::WARN ) << "Spatial Reference: SRS xform not possible" << std::endl << " From => " << input_sr->getWKT() << std::endl << " To => " << this->getWKT() << std::endl; return false; } //TODO: figure out why xforming GEOCS x=-180 to another GEOCS doesn't work if ( OCTTransform( xform_handle, 1, &input.x(), &input.y(), &input.z() ) ) { result = true; } else { osgGIS::notify( osg::WARN ) << "Spatial Reference: Failed to xform a point from " << input_sr->getName() << " to " << this->getName() << std::endl; } OCTDestroyCoordinateTransformation( xform_handle ); } else { result = true; } // put it into the new ref frame: if ( !mat_equiv ) { input.set( input * ref_frame ); } if ( result == true ) { applyTo( input ); } return result; }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, double& out_elevation, double desiredResolution, double* out_actualResolution) { osg::Timer_t start = osg::Timer::instance()->tick(); if ( _mapf.elevationLayers().empty() ) { // this means there are no heightfields. out_elevation = 0.0; return true; } // tile size (resolution of elevation tiles) unsigned tileSize = std::max(_mapf.getMapOptions().elevationTileSize().get(), 2u); //This is the max resolution that we actually have data at this point unsigned int bestAvailLevel = getMaxLevel( point.x(), point.y(), point.getSRS(), _mapf.getProfile()); if (desiredResolution > 0.0) { unsigned int desiredLevel = _mapf.getProfile()->getLevelOfDetailForHorizResolution( desiredResolution, tileSize ); if (desiredLevel < bestAvailLevel) bestAvailLevel = desiredLevel; } OE_DEBUG << LC << "Best available data level " << point.x() << ", " << point.y() << " = " << bestAvailLevel << std::endl; // transform the input coords to map coords: GeoPoint mapPoint = point; if ( point.isValid() && !point.getSRS()->isHorizEquivalentTo( _mapf.getProfile()->getSRS() ) ) { mapPoint = point.transform(_mapf.getProfile()->getSRS()); if ( !mapPoint.isValid() ) { OE_WARN << LC << "Fail: coord transform failed" << std::endl; return false; } } // get the tilekey corresponding to the tile we need: TileKey key = _mapf.getProfile()->createTileKey( mapPoint.x(), mapPoint.y(), bestAvailLevel ); if ( !key.valid() ) { OE_WARN << LC << "Fail: coords fall outside map" << std::endl; return false; } bool result = false; while (!result) { GeoHeightField geoHF; TileCache::Record record; // Try to get the hf from the cache if ( _cache.get( key, record ) ) { geoHF = record.value(); } else { // Create it osg::ref_ptr<osg::HeightField> hf = new osg::HeightField(); hf->allocate( tileSize, tileSize ); // Initialize the heightfield to nodata for (unsigned int i = 0; i < hf->getFloatArray()->size(); i++) { hf->getFloatArray()->at( i ) = NO_DATA_VALUE; } if (_mapf.populateHeightField( hf, key ) ) { geoHF = GeoHeightField( hf.get(), key.getExtent() ); _cache.insert( key, geoHF ); } } if (geoHF.valid()) { float elevation = 0.0f; result = geoHF.getElevation( mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), _mapf.getMapInfo().getElevationInterpolation(), mapPoint.getSRS(), elevation); if (result && elevation != NO_DATA_VALUE) { // see what the actual resolution of the heightfield is. if ( out_actualResolution ) *out_actualResolution = geoHF.getXInterval(); out_elevation = (double)elevation; break; } else { result = false; } } if (!result) { key = key.createParentKey(); if (!key.valid()) { break; } } } osg::Timer_t end = osg::Timer::instance()->tick(); _queries++; _totalTime += osg::Timer::instance()->delta_s( start, end ); return result; }