bool getIsectPoint( const GeoPoint& p1, const GeoPoint& p2, const GeoPoint& p3, const GeoPoint& p4, GeoPoint& out ) { double denom = (p4.y()-p3.y())*(p2.x()-p1.x()) - (p4.x()-p3.x())*(p2.y()-p1.y()); if ( denom == 0.0 ) { out = GeoPoint::invalid(); // parallel lines return false; } double ua_num = (p4.x()-p3.x())*(p1.y()-p3.y()) - (p4.y()-p3.y())*(p1.x()-p3.x()); double ub_num = (p2.x()-p1.x())*(p1.y()-p3.y()) - (p2.y()-p1.y())*(p1.x()-p3.x()); double ua = ua_num/denom; double ub = ub_num/denom; if ( ua < 0.0 || ua > 1.0 ) // || ub < 0.0 || ub > 1.0 ) { out = GeoPoint::invalid(); // isect point is on line, but not on line segment return false; } double x = p1.x() + ua*(p2.x()-p1.x()); double y = p1.y() + ua*(p2.y()-p1.y()); double z = p1.getDim() > 2? p1.z() + ua*(p2.z()-p1.z()) : 0.0; //right? out = GeoPoint( x, y, z, p1.getSRS() ); return true; }
static void applyBlast(GeoPoint& center, double radius, double offset, const TileKey& key, osg::HeightField* heightField) { //Get the extents of the tile double xmin, ymin, xmax, ymax; key.getExtent().getBounds(xmin, ymin, xmax, ymax); int tileSize = heightField->getNumColumns(); // Iterate over the output heightfield and sample the data that was read into it. double dx = (xmax - xmin) / (tileSize-1); double dy = (ymax - ymin) / (tileSize-1); const SpatialReference* srs = SpatialReference::create("wgs84"); for (int c = 0; c < tileSize; ++c) { double geoX = xmin + (dx * (double)c); for (int r = 0; r < tileSize; ++r) { double geoY = ymin + (dy * (double)r); GeoPoint geo(srs, geoX, geoY, center.z(), ALTMODE_ABSOLUTE); double distance = geo.distanceTo( center ); double ratio = distance / radius; if (ratio <= 1.0) { double weight = 1.0 - osg::clampBetween(ratio, 0.0, 1.0); if (weight > 0) { float h = center.z() + offset * weight; heightField->setHeight(c, r, h); } } /* if ( boundary->contains2D(geo.x(), geo.y()) ) { float h = heightField->getHeight( c, r ); if (h == NO_DATA_VALUE) { //h = deformation._offset; } else { //h += deformation._offset; h = deformation._offset; } heightField->setHeight(c, r, h); } */ } } }
/* method: z of class GeoPoint */ static int tolua_Lua_ScriptEngine_tolua_GeoPoint_z00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"GeoPoint",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { GeoPoint* self = (GeoPoint*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'z'",NULL); #endif { double tolua_ret = (double) self->z(); tolua_pushnumber(tolua_S,(double)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'z'.",&tolua_err); return 0; #endif }
void ElevationLOD::traverse( osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv ); osg::Vec3d eye, center, up; eye = cv->getViewPoint(); float height = eye.z(); if (_srs) { GeoPoint mapPoint; mapPoint.fromWorld( _srs, eye ); height = mapPoint.z(); } //OE_NOTICE << "Height " << height << std::endl; if (height >= _minElevation && height <= _maxElevation) { osg::Group::traverse( nv ); } else { //OE_NOTICE << "Elevation " << height << " outside of range " << _minElevation << " to " << _maxElevation << std::endl; } } else { osg::Group::traverse( nv ); } }
void ElevationLOD::traverse( osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR && nv.getTraversalMode() == osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN ) { bool rangeOK = true; bool altitudeOK = true; // first test the range: if ( _minRange.isSet() || _maxRange.isSet() ) { float range = nv.getDistanceToViewPoint( getBound().center(), true ); rangeOK = (!_minRange.isSet() || (range >= *_minRange)) && (!_maxRange.isSet() || (range <= *_maxRange)); } if ( rangeOK ) { if ( _minElevation.isSet() || _maxElevation.isSet() ) { double alt; // first see if we have a precalculated elevation: osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); osg::Vec3d eye = cv->getViewPoint(); if ( _srs && !_srs->isProjected() ) { GeoPoint mapPoint; mapPoint.fromWorld( _srs.get(), eye ); alt = mapPoint.z(); } else { alt = eye.z(); } // account for the LOD scale alt *= cv->getLODScale(); altitudeOK = (!_minElevation.isSet() || (alt >= *_minElevation)) && (!_maxElevation.isSet() || (alt <= *_maxElevation)); } if ( altitudeOK ) { std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv)); } } } else { osg::Group::traverse( nv ); } }
bool AnnotationNode::makeAbsolute( GeoPoint& mapPoint, osg::Node* patch ) const { // in terrain-clamping mode, force it to HAT=0: if ( _altitude.valid() && ( _altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN || _altitude->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) ) { mapPoint.altitudeMode() = ALTMODE_RELATIVE; //If we're clamping to the terrain if (_altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN) { mapPoint.z() = 0.0; } } // if the point's already absolute and we're not clamping it, nop. if ( mapPoint.altitudeMode() == ALTMODE_ABSOLUTE ) { return true; } // calculate the absolute Z of the map point. if ( getMapNode() ) { // find the terrain height at the map point: double hamsl; if (getMapNode()->getTerrain()->getHeight(patch, mapPoint.getSRS(), mapPoint.x(), mapPoint.y(), &hamsl, 0L)) { // apply any scale/offset in the symbology: if ( _altitude.valid() ) { if ( _altitude->verticalScale().isSet() ) hamsl *= _altitude->verticalScale()->eval(); if ( _altitude->verticalOffset().isSet() ) hamsl += _altitude->verticalOffset()->eval(); } mapPoint.z() += hamsl; } mapPoint.altitudeMode() = ALTMODE_ABSOLUTE; return true; } return false; }
void TerrainProfileGraph::mouseReleaseEvent(QMouseEvent* e) { if (_selecting) { double selectEnd = mapToScene(e->pos()).x(); double zoomStart = osg::minimum(_selectStart, selectEnd); double zoomEnd = osg::maximum(_selectStart, selectEnd); double startDistanceFactor = ((zoomStart - _graphField.x()) / (double)_graphField.width()); double endDistanceFactor = ((zoomEnd - _graphField.x()) / (double)_graphField.width()); osg::Vec3d worldStart, worldEnd; _calculator->getStart(ALTMODE_ABSOLUTE).toWorld(worldStart); _calculator->getEnd(ALTMODE_ABSOLUTE).toWorld(worldEnd); double newStartWorldX = (worldEnd.x() - worldStart.x()) * startDistanceFactor + worldStart.x(); double newStartWorldY = (worldEnd.y() - worldStart.y()) * startDistanceFactor + worldStart.y(); double newStartWorldZ = (worldEnd.z() - worldStart.z()) * startDistanceFactor + worldStart.z(); GeoPoint newStart; newStart.fromWorld(_calculator->getStart().getSRS(), osg::Vec3d(newStartWorldX, newStartWorldY, newStartWorldZ)); newStart.z() = 0.0; double newEndWorldX = (worldEnd.x() - worldStart.x()) * endDistanceFactor + worldStart.x(); double newEndWorldY = (worldEnd.y() - worldStart.y()) * endDistanceFactor + worldStart.y(); double newEndtWorldZ = (worldEnd.z() - worldStart.z()) * endDistanceFactor + worldStart.z(); GeoPoint newEnd; newEnd.fromWorld(_calculator->getStart().getSRS(), osg::Vec3d(newEndWorldX, newEndWorldY, newEndtWorldZ)); newEnd.z() = 0.0; if (osg::absolute(newEnd.x() - newStart.x()) > 0.001 || osg::absolute(newEnd.y() - newStart.y()) > 0.001) { _calculator->setStartEnd(newStart, newEnd); } else { _selecting = false; drawHoverCursor(mapToScene(e->pos())); } } _selecting = false; }
void MouseCoordsLabelCallback::set( const GeoPoint& mapCoords, osg::View* view, MapNode* mapNode ) { if ( _label.valid() ) { _label->setText( Stringify() << _formatter->format( mapCoords ) << ", " << mapCoords.z() ); } }
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()); }
void update( float x, float y, osgViewer::View* view ) { bool yes = false; // look under the mouse: osg::Vec3d world; if ( _terrain->getWorldCoordsUnderMouse(view, x, y, world) ) { // convert to map coords: GeoPoint mapPoint; mapPoint.fromWorld( _terrain->getSRS(), world ); // do an elevation query: double query_resolution = 0.1; // 1/10th of a degree double out_hamsl = 0.0; double out_resolution = 0.0; bool ok = _query.getElevation( mapPoint, out_hamsl, query_resolution, &out_resolution ); if ( ok ) { // convert to geodetic to get the HAE: mapPoint.z() = out_hamsl; GeoPoint mapPointGeodetic( s_mapNode->getMapSRS()->getGeodeticSRS(), mapPoint ); static LatLongFormatter s_f; s_posLabel->setText( Stringify() << std::fixed << std::setprecision(2) << s_f.format(mapPointGeodetic.y()) << ", " << s_f.format(mapPointGeodetic.x()) ); s_mslLabel->setText( Stringify() << out_hamsl ); s_haeLabel->setText( Stringify() << mapPointGeodetic.z() ); s_resLabel->setText( Stringify() << out_resolution ); yes = true; } } if (!yes) { s_posLabel->setText( "-" ); s_mslLabel->setText( "-" ); s_haeLabel->setText( "-" ); s_resLabel->setText( "-" ); } }
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 Dragger::updateTransform(osg::Node* patch) { osg::Matrixd matrix; GeoPoint mapPoint; _mapNode->getMap()->toMapPoint( _position, mapPoint ); //Get the height if (_position.altitudeMode() == ALTMODE_RELATIVE) { double hamsl; if (_mapNode->getTerrain()->getHeight(mapPoint.x(), mapPoint.y(), &hamsl, 0L, patch)) { mapPoint.z() += hamsl; } mapPoint.altitudeMode() = ALTMODE_ABSOLUTE; } mapPoint.createLocalToWorld( matrix ); setMatrix( matrix ); }
bool visitPoint( GeoPoint& p ) { bool ok = true; // pull it out of the source reference frame: p.set( p * src_rf ); // reproject it: if ( handle ) ok = OCTTransform( handle, 1, &p.x(), &p.y(), &p.z() ) != 0; // push it into the new reference frame: p.set( p * to_srs->getReferenceFrame() ); p = p.getDim() == 2? GeoPoint( p.x(), p.y(), to_srs ) : GeoPoint( p.x(), p.y(), p.z(), to_srs ); return ok; }
void LOSCreationDialog::centerMapOnNode(osg::Node* node) { if (node && _map.valid() && _manager.valid() && _views) { AnnotationNode* annoNode = dynamic_cast<AnnotationNode*>(node); if (annoNode && annoNode->getAnnotationData() && annoNode->getAnnotationData()->getViewpoint()) { _manager->doAction(this, new SetViewpointAction(osgEarth::Viewpoint(*annoNode->getAnnotationData()->getViewpoint()), *_views)); } else { osg::Vec3d center = node->getBound().center(); GeoPoint output; output.fromWorld( _map->getSRS(), center ); //_map->worldPointToMapPoint(center, output); _manager->doAction(this, new SetViewpointAction(osgEarth::Viewpoint( "center", output.x(), output.y(), output.z(), 0.0, -90.0, 1e5), *_views)); } } }
int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); if ( arguments.read("--stencil") ) osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 ); //Setup a CompositeViewer osgViewer::CompositeViewer viewer(arguments); //Setup our main view that will show the loaded earth file. osgViewer::View* mainView = new osgViewer::View(); mainView->getCamera()->setNearFarRatio(0.00002); mainView->setCameraManipulator( new EarthManipulator() ); mainView->setUpViewInWindow( 50, 50, 800, 800 ); viewer.addView( mainView ); //Setup a MiniMap View that will be embedded in the main view int miniMapWidth = 400; int miniMapHeight = 200; osgViewer::View* miniMapView = new osgViewer::View(); miniMapView->getCamera()->setNearFarRatio(0.00002); miniMapView->getCamera()->setViewport( 0, 0, miniMapWidth, miniMapHeight); miniMapView->setCameraManipulator( new EarthManipulator() ); miniMapView->getCamera()->setClearColor( osg::Vec4(0,0,0,0)); miniMapView->getCamera()->setProjectionResizePolicy( osg::Camera::FIXED ); miniMapView->getCamera()->setProjectionMatrixAsPerspective(30.0, double(miniMapWidth) / double(miniMapHeight), 1.0, 1000.0); //Share a graphics context with the main view miniMapView->getCamera()->setGraphicsContext( mainView->getCamera()->getGraphicsContext()); viewer.addView( miniMapView ); // load an earth file, and support all or our example command-line options // and earth file <external> tags osg::Node* node = MapNodeHelper().load( arguments, mainView ); if ( node ) { MapNode* mapNode = MapNode::findMapNode(node); //Set the main view's scene data to the loaded earth file mainView->setSceneData( node ); //Setup a group to hold the contents of the MiniMap osg::Group* miniMapGroup = new osg::Group; MapNode* miniMapNode = makeMiniMapNode(); miniMapGroup->addChild( miniMapNode ); //Get the main MapNode so we can do tranformations between it and our minimap MapNode* mainMapNode = MapNode::findMapNode( node ); //Set the scene data for the minimap miniMapView->setSceneData( miniMapGroup ); //Add a marker we can move around with the main view's eye point Style markerStyle; markerStyle.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" ); PlaceNode* eyeMarker = new PlaceNode(miniMapNode, GeoPoint(miniMapNode->getMapSRS(), 0, 0), "", markerStyle); miniMapGroup->addChild( eyeMarker ); miniMapGroup->getOrCreateStateSet()->setRenderBinDetails(100, "RenderBin"); osg::Node* bounds = 0; while (!viewer.done()) { //Reset the viewport so that the camera's viewport is static and doesn't resize with window resizes miniMapView->getCamera()->setViewport( 0, 0, miniMapWidth, miniMapHeight); //Get the eye point of the main view osg::Vec3d eye, up, center; mainView->getCamera()->getViewMatrixAsLookAt( eye, center, up ); //Turn the eye into a geopoint and transform it to the minimap's SRS GeoPoint eyeGeo; eyeGeo.fromWorld( mainMapNode->getMapSRS(), eye ); eyeGeo.transform( miniMapNode->getMapSRS()); //We want the marker to be positioned at elevation 0, so zero out any elevation in the eye point eyeGeo.z() = 0; //Set the position of the marker eyeMarker->setPosition( eyeGeo ); if (bounds) { miniMapGroup->removeChild( bounds ); } GeoExtent extent = getExtent( mainView ); bounds = drawBounds( miniMapNode, extent ); miniMapGroup->addChild( bounds ); viewer.frame(); } } else { OE_NOTICE << "\nUsage: " << argv[0] << " file.earth" << std::endl << MapNodeHelper().usage() << std::endl; } return 0; }
void update( float x, float y, osgViewer::View* view ) { bool yes = false; // look under the mouse: osg::Vec3d world; osgUtil::LineSegmentIntersector::Intersections hits; if ( view->computeIntersections(x, y, hits) ) { world = hits.begin()->getWorldIntersectPoint(); // convert to map coords: GeoPoint mapPoint; mapPoint.fromWorld( _terrain->getSRS(), world ); mapPoint.z() = 0; // do an elevation query: double query_resolution = 0; // max. double out_hamsl = 0.0; double out_resolution = 0.0; bool ok = _query.getElevation( mapPoint, out_hamsl, query_resolution, &out_resolution ); mapPoint.z() = out_hamsl; _mapPoint = mapPoint; GeometryFactory factory(SpatialReference::create("wgs84")); Geometry* geom = 0; if (_tool == TOOL_RECTANGLE) { geom = factory.createRectangle(mapPoint.vec3d(), _radius,_radius); } else if (_tool == TOOL_CIRCLE || _tool == TOOL_BLAST) { geom = factory.createCircle(mapPoint.vec3d(), _radius); } Feature* feature = new Feature(geom, SpatialReference::create("wgs84")); if (_featureNode.valid()) { _root->removeChild( _featureNode ); _featureNode = 0; } Style style; style.getOrCreateSymbol<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; style.getOrCreateSymbol<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE; if (_tool != TOOL_BLAST) { style.getOrCreateSymbol<PolygonSymbol>()->fill()->color() = Color(Color::Cyan, 0.5); } else { style.getOrCreateSymbol<PolygonSymbol>()->fill()->color() = Color(Color::Red, 0.5); } _featureNode = new FeatureNode( s_mapNode, feature, style); _root->addChild( _featureNode ); } }
bool ElevationDragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { bool ret = true; if (ea.getHandled()) { ret = false; } else { bool handled = false; if (_elevationMode) { if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH) { ret = osgEarth::Dragger::handle(ea, aa); if (ret) { bool pressedAlt = ((ea.getModKeyMask() & _modKeyMask) > 0); if (pressedAlt) { _pointer.reset(); // set movement range // TODO: values 0.0 and 300000.0 are rather experimental GeoPoint posStart(_position.getSRS(), _position.x(), _position.y(), 0.0, ALTMODE_ABSOLUTE); osg::Vec3d posStartXYZ; posStart.toWorld(posStartXYZ); GeoPoint posEnd(_position.getSRS(), _position.x(), _position.y(), 300000.0, ALTMODE_ABSOLUTE); osg::Vec3d posEndXYZ; posEnd.toWorld(posEndXYZ); _projector->setLine(posStartXYZ, posEndXYZ); // set camera osgUtil::LineSegmentIntersector::Intersections intersections; osg::Node::NodeMask intersectionMask = 0xffffffff; osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (view->computeIntersections(ea.getX(),ea.getY(),intersections, intersectionMask)) { for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint()); } for (osg::NodePath::iterator itr = _pointer._hitList.front().first.begin(); itr != _pointer._hitList.front().first.end(); ++itr) { ElevationDragger* dragger = dynamic_cast<ElevationDragger*>(*itr); if (dragger==this) { osg::Camera *rootCamera = view->getCamera(); osg::NodePath nodePath = _pointer._hitList.front().first; osg::NodePath::reverse_iterator ritr; for (ritr = nodePath.rbegin(); ritr != nodePath.rend(); ++ritr) { osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr); if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) { rootCamera = camera; break; } } _pointer.setCamera(rootCamera); _pointer.setMousePosition(ea.getX(), ea.getY()); } } } _elevationDragging = true; } } handled = true; } else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) { _elevationDragging = false; } else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) { if (_elevationDragging) { _pointer._hitIter = _pointer._hitList.begin(); _pointer.setMousePosition(ea.getX(), ea.getY()); if (_projector->project(_pointer, _startProjectedPoint)) { //Get the absolute mapPoint that they've drug it to. GeoPoint projectedPos; projectedPos.fromWorld(_position.getSRS(), _startProjectedPoint); // make sure point is not dragged down below // TODO: think of a better solution / HeightAboveTerrain performance issues? if (projectedPos.z() > 0) { //If the current position is relative, we need to convert the absolute world point to relative. //If the point is absolute then just emit the absolute point. if (_position.altitudeMode() == ALTMODE_RELATIVE) { projectedPos.alt() = _position.alt(); projectedPos.altitudeMode() = ALTMODE_RELATIVE; } setPosition( projectedPos ); aa.requestRedraw(); } } handled = true; } } } if (!handled) { ret = osgEarth::Dragger::handle(ea, aa); } } return ret; }
void update( float x, float y, osgViewer::View* view ) { bool yes = false; // look under the mouse: osg::Vec3d world; osgUtil::LineSegmentIntersector::Intersections hits; if ( view->computeIntersections(x, y, hits) ) { world = hits.begin()->getWorldIntersectPoint(); // convert to map coords: GeoPoint mapPoint; mapPoint.fromWorld( _terrain->getSRS(), world ); // do an elevation query: double query_resolution = 0; // 1/10th of a degree double out_hamsl = 0.0; double out_resolution = 0.0; bool ok = _query.getElevation( mapPoint, out_hamsl, query_resolution, &out_resolution ); if ( ok ) { // convert to geodetic to get the HAE: mapPoint.z() = out_hamsl; GeoPoint mapPointGeodetic( s_mapNode->getMapSRS()->getGeodeticSRS(), mapPoint ); static LatLongFormatter s_f; s_posLabel->setText( Stringify() << std::fixed << std::setprecision(2) << s_f.format(mapPointGeodetic.y()) << ", " << s_f.format(mapPointGeodetic.x()) ); s_mslLabel->setText( Stringify() << out_hamsl ); s_haeLabel->setText( Stringify() << mapPointGeodetic.z() ); s_resLabel->setText( Stringify() << out_resolution ); yes = true; } // finally, get a normal ISECT HAE point. GeoPoint isectPoint; isectPoint.fromWorld( _terrain->getSRS()->getGeodeticSRS(), world ); s_mapLabel->setText( Stringify() << isectPoint.alt() ); } if (!yes) { s_posLabel->setText( "-" ); s_mslLabel->setText( "-" ); s_haeLabel->setText( "-" ); s_resLabel->setText( "-" ); } }
void AutoClipPlaneCullCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) { if ( _active ) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); if ( cv ) { osgEarth::Map* map = _mapNode.valid() ? _mapNode->getMap() : 0; osg::Camera* cam = cv->getCurrentCamera(); osg::ref_ptr<osg::CullSettings::ClampProjectionMatrixCallback>& clamper = _clampers.get(cam); if ( !clamper.valid() ) { clamper = new CustomProjClamper(); cam->setClampProjectionMatrixCallback( clamper.get() ); OE_INFO << LC << "Installed custom projeciton matrix clamper" << std::endl; } else { CustomProjClamper* c = static_cast<CustomProjClamper*>(clamper.get()); osg::Vec3d eye, center, up; cam->getViewMatrixAsLookAt( eye, center, up ); // clamp the far clipping plane to the approximate horizon distance if ( _autoFarPlaneClamping ) { double d = eye.length(); c->_maxFar = sqrt( d*d - _rp2 ); } else { c->_maxFar = DBL_MAX; } // get the height-above-ellipsoid. If we need to be more accurate, we can use // ElevationQuery in the future.. //osg::Vec3d loc; GeoPoint loc; if ( map ) { loc.fromWorld( map->getSRS(), eye ); //map->worldPointToMapPoint( eye, loc ); } else { static osg::EllipsoidModel em; osg::Vec3d t; em.convertXYZToLatLongHeight( eye.x(), eye.y(), eye.z(), loc.y(), loc.x(), loc.z() ); } //double hae = loc.z(); double hae = loc.z(); if (_mapNode.valid()) { double height = 0.0; _mapNode->getTerrain()->getHeight(loc.getSRS(), loc.x(), loc.y(), &height); //OE_NOTICE << "got height " << height << std::endl; hae -= height; //OE_NOTICE << "HAE=" << hae << std::endl; } // ramp a new near/far ratio based on the HAE. c->_nearFarRatio = Utils::remap( hae, 0.0, _haeThreshold, _minNearFarRatio, _maxNearFarRatio ); } #if 0 { double n, f, a, v; cv->getProjectionMatrix()->getPerspective(v, a, n, f); OE_INFO << std::setprecision(16) << "near = " << n << ", far = " << f << ", ratio = " << n/f << std::endl; } #endif } } traverse( node, nv ); }
void GeodeticGraticule::cull(osgUtil::CullVisitor* cv) { osg::Matrixd viewMatrix = *cv->getModelViewMatrix(); osg::Vec3d vp = cv->getViewPoint(); CameraData& cdata = getCameraData(cv->getCurrentCamera()); // Only update if the view matrix has changed. if (viewMatrix != cdata._lastViewMatrix && _mapNode.valid()) { GeoPoint eyeGeo; eyeGeo.fromWorld(_mapNode->getMapSRS(), vp); cdata._lon = eyeGeo.x(); cdata._lat = eyeGeo.y(); osg::Viewport* viewport = cv->getViewport(); float centerX = viewport->x() + viewport->width() / 2.0; float centerY = viewport->y() + viewport->height() / 2.0; float offsetCenterX = centerX; float offsetCenterY = centerY; bool hitValid = false; // Try the center of the screen. osg::Vec3d focalPoint; if (_mapNode->getTerrain()->getWorldCoordsUnderMouse(cv->getCurrentCamera()->getView(), centerX, centerY, focalPoint)) { hitValid = true; } if (hitValid) { GeoPoint focalGeo; focalGeo.fromWorld(_mapNode->getMapSRS(), focalPoint); cdata._lon = focalGeo.x(); cdata._lat = focalGeo.y(); // We only store the previous view matrix if we actually got a hit. Otherwise we still need to update. cdata._lastViewMatrix = viewMatrix; } // Get the view extent. cdata._viewExtent = getViewExtent(cv); double targetResolution = (cdata._viewExtent.height() / 180.0) / options().gridLines().get(); double resolution = _resolutions[0]; for (unsigned int i = 0; i < _resolutions.size(); i++) { resolution = _resolutions[i]; if (resolution <= targetResolution) { break; } } // Trippy //resolution = targetResolution; // Try to compute an approximate meters to pixel value at this view. double dist = osg::clampAbove(eyeGeo.z(), 1.0); double halfWidth; const osg::Matrix& proj = *cv->getProjectionMatrix(); bool isOrtho = osg::equivalent(proj(3,3), 1.0); if (isOrtho) { double L, R, B, T, N, F; proj.getOrtho(L, R, B, T, N, F); halfWidth = 0.5*(R-L); } else // perspective { double fovy, aspectRatio, zNear, zFar; cv->getProjectionMatrix()->getPerspective(fovy, aspectRatio, zNear, zFar); halfWidth = osg::absolute(tan(osg::DegreesToRadians(fovy / 2.0)) * dist); } cdata._metersPerPixel = (2.0 * halfWidth) / (double)viewport->height(); if (cdata._resolution != resolution) { cdata._resolution = (float)resolution; cdata._resolutionUniform->set(cdata._resolution); } OE_TEST << "EW=" << cdata._viewExtent.width() << ", ortho=" << isOrtho << ", hW=" << halfWidth << ", res=" << resolution << ", mPP=" << cdata._metersPerPixel << std::endl; } // traverse the label pool for this camera. cv->pushStateSet(cdata._labelStateset.get()); for (std::vector< osg::ref_ptr< LabelNode > >::iterator i = cdata._labelPool.begin(); i != cdata._labelPool.end(); ++i) { i->get()->accept(*cv); } cv->popStateSet(); }
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; }
void GraticuleNode::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { updateLabels(); } else if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv); osg::Vec3d vp = cv->getViewPoint(); osg::Matrixd viewMatrix = *cv->getModelViewMatrix(); // Only update if the view matrix has changed. if (viewMatrix != _viewMatrix) { GeoPoint eyeGeo; eyeGeo.fromWorld( _mapNode->getMapSRS(), vp ); _lon = eyeGeo.x(); _lat = eyeGeo.y(); osg::Viewport* viewport = cv->getViewport(); float centerX = viewport->x() + viewport->width() / 2.0; float centerY = viewport->y() + viewport->height() / 2.0; float offsetCenterX = centerX; float offsetCenterY = centerY; bool hitValid = false; // Try the center of the screen. if(_mapNode->getTerrain()->getWorldCoordsUnderMouse(cv->getCurrentCamera()->getView(), centerX, centerY, _focalPoint)) { hitValid = true; } if (hitValid) { GeoPoint focalGeo; focalGeo.fromWorld( _mapNode->getMapSRS(), _focalPoint ); _lon = focalGeo.x(); _lat = focalGeo.y(); // We only store the previous view matrix if we actually got a hit. Otherwise we still need to update. _viewMatrix = viewMatrix; } double targetResolution = (_viewExtent.height() / 180.0) / _options.gridLines().get(); double resolution = _resolutions[0]; for (unsigned int i = 0; i < _resolutions.size(); i++) { resolution = _resolutions[i]; if (resolution <= targetResolution) { break; } } // Trippy //resolution = targetResolution; _viewExtent = getViewExtent( cv ); // Try to compute an approximate meters to pixel value at this view. double fovy, aspectRatio, zNear, zFar; cv->getProjectionMatrix()->getPerspective(fovy, aspectRatio, zNear, zFar); double dist = osg::clampAbove(eyeGeo.z(), 1.0); double halfWidth = osg::absolute( tan(osg::DegreesToRadians(fovy/2.0)) * dist ); _metersPerPixel = (2.0 * halfWidth) / (double)viewport->height(); if (_resolution != resolution) { setResolution(resolution); } } } osg::Group::traverse(nv); }
bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getHandled()) return false; osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (!view) return false; if (!_mapNode.valid()) return false; if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH) { Picker picker( view, this ); Picker::Hits hits; if ( picker.pick( ea.getX(), ea.getY(), hits ) ) { _dragging = true; //Check for and handle vertical dragging if necessary bool pressedAlt = _modKeyMask && (ea.getModKeyMask() & _modKeyMask) > 0; _elevationDragging = (_defaultMode == Dragger::DRAGMODE_VERTICAL && !pressedAlt) || (_defaultMode == Dragger::DRAGMODE_HORIZONTAL && pressedAlt); if (_elevationDragging) { _pointer.reset(); // set movement range // TODO: values 0.0 and 300000.0 are rather experimental GeoPoint posStart(_position.getSRS(), _position.x(), _position.y(), 0.0, ALTMODE_ABSOLUTE); osg::Vec3d posStartXYZ; posStart.toWorld(posStartXYZ); GeoPoint posEnd(_position.getSRS(), _position.x(), _position.y(), 300000.0, ALTMODE_ABSOLUTE); osg::Vec3d posEndXYZ; posEnd.toWorld(posEndXYZ); _projector->setLine(posStartXYZ, posEndXYZ); // set camera osgUtil::LineSegmentIntersector::Intersections intersections; osg::Node::NodeMask intersectionMask = 0xffffffff; osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (view->computeIntersections(ea.getX(),ea.getY(),intersections, intersectionMask)) { for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint()); } bool draggerFound = false; for (osgManipulator::PointerInfo::IntersectionList::iterator piit = _pointer._hitList.begin(); piit != _pointer._hitList.end(); ++piit) { for (osg::NodePath::iterator itr = piit->first.begin(); itr != piit->first.end(); ++itr) { Dragger* dragger = dynamic_cast<Dragger*>(*itr); if (dragger==this) { draggerFound = true; osg::Camera *rootCamera = view->getCamera(); osg::NodePath nodePath = _pointer._hitList.front().first; osg::NodePath::reverse_iterator ritr; for (ritr = nodePath.rbegin(); ritr != nodePath.rend(); ++ritr) { osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr); if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) { rootCamera = camera; break; } } _pointer.setCamera(rootCamera); _pointer.setMousePosition(ea.getX(), ea.getY()); break; } } if (draggerFound) break; } } } aa.requestRedraw(); return true; } } else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) { _elevationDragging = false; if ( _dragging ) { _dragging = false; firePositionChanged(); } aa.requestRedraw(); } else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) { if (_elevationDragging) { _pointer._hitIter = _pointer._hitList.begin(); _pointer.setMousePosition(ea.getX(), ea.getY()); if (_projector->project(_pointer, _startProjectedPoint)) { //Get the absolute mapPoint that they've drug it to. GeoPoint projectedPos; projectedPos.fromWorld(_position.getSRS(), _startProjectedPoint); // make sure point is not dragged down below // TODO: think of a better solution / HeightAboveTerrain performance issues? if (projectedPos.z() >= _verticalMinimum) { //If the current position is relative, we need to convert the absolute world point to relative. //If the point is absolute then just emit the absolute point. if (_position.altitudeMode() == ALTMODE_RELATIVE) { projectedPos.transformZ(ALTMODE_RELATIVE, getMapNode()->getTerrain()); } setPosition( projectedPos ); aa.requestRedraw(); } } return true; } if (_dragging) { osg::Vec3d world; if ( getMapNode() && getMapNode()->getTerrain()->getWorldCoordsUnderMouse(view, ea.getX(), ea.getY(), world) ) { //Get the absolute mapPoint that they've drug it to. GeoPoint mapPoint; mapPoint.fromWorld( getMapNode()->getMapSRS(), world ); //_mapNode->getMap()->worldPointToMapPoint(world, mapPoint); //If the current position is relative, we need to convert the absolute world point to relative. //If the point is absolute then just emit the absolute point. if (_position.altitudeMode() == ALTMODE_RELATIVE) { mapPoint.alt() = _position.alt(); mapPoint.altitudeMode() = ALTMODE_RELATIVE; } setPosition( mapPoint ); aa.requestRedraw(); return true; } } } else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE) { Picker picker( view, this ); Picker::Hits hits; if ( picker.pick( ea.getX(), ea.getY(), hits ) ) { setHover( true ); } else { setHover( false ); } aa.requestRedraw(); } return false; }
void update( float x, float y, osgViewer::View* view ) { bool yes = false; // look under the mouse: osg::Vec3d world; osgUtil::LineSegmentIntersector::Intersections hits; if ( view->computeIntersections(x, y, hits) ) { world = hits.begin()->getWorldIntersectPoint(); // convert to map coords: GeoPoint mapPoint; mapPoint.fromWorld( _terrain->getSRS(), world ); // do an elevation query: double query_resolution = 0.0; // max. double actual_resolution = 0.0; float elevation = 0.0f; elevation = _query.getElevation( mapPoint, query_resolution, &actual_resolution ); if ( elevation != NO_DATA_VALUE ) { // convert to geodetic to get the HAE: mapPoint.z() = elevation; GeoPoint mapPointGeodetic( s_mapNode->getMapSRS()->getGeodeticSRS(), mapPoint ); static LatLongFormatter s_f; s_posLabel->setText( Stringify() << std::fixed << std::setprecision(2) << s_f.format(mapPointGeodetic.y(), true) << ", " << s_f.format(mapPointGeodetic.x(), false) ); if (s_mapNode->getMapSRS()->isGeographic()) { osg::ref_ptr<const SpatialReference> tm = s_mapNode->getMapSRS()->createUTMFromLonLat(mapPointGeodetic.x(), mapPointGeodetic.y()); actual_resolution = tm->transformUnits(Distance(actual_resolution, Units::DEGREES), tm.get(), mapPointGeodetic.y()); } s_mslLabel->setText( Stringify() << elevation << " m" ); s_haeLabel->setText( Stringify() << mapPointGeodetic.z() << " m" ); s_resLabel->setText( Stringify() << actual_resolution << " m" ); double egm96z = mapPoint.z(); VerticalDatum::transform( mapPointGeodetic.getSRS()->getVerticalDatum(), VerticalDatum::get("egm96"), mapPointGeodetic.y(), mapPointGeodetic.x(), egm96z); s_egm96Label->setText(Stringify() << egm96z << " m"); yes = true; } // finally, get a normal ISECT HAE point. GeoPoint isectPoint; isectPoint.fromWorld( _terrain->getSRS()->getGeodeticSRS(), world ); s_mapLabel->setText( Stringify() << isectPoint.alt() << " m"); // and move the marker. s_marker->setPosition(mapPoint); } if (!yes) { s_posLabel->setText( "-" ); s_mslLabel->setText( "-" ); s_haeLabel->setText( "-" ); s_resLabel->setText( "-" ); s_egm96Label->setText("-"); } }
bool ElevationQuery::getElevationImpl(const GeoPoint& point, float& 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 ( _terrainModelLayers.size() > 0 ) { osgUtil::IntersectionVisitor iv; if ( _ivrc.valid() ) iv.setReadCallback(_ivrc.get()); for(LayerVector::iterator i = _terrainModelLayers.begin(); i != _terrainModelLayers.end(); ++i) { // find the scene graph for this layer: Layer* layer = i->get(); osg::Node* node = layer->getNode(); 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 ( !_lsi.valid() ) { _lsi = new osgUtil::LineSegmentIntersector(start, end); _lsi->setIntersectionLimit( _lsi->LIMIT_NEAREST ); } else { _lsi->reset(); _lsi->setStart( start ); _lsi->setEnd ( end ); } // try it. iv.setIntersector( _lsi.get() ); node->accept( iv ); // check for a result!! if ( _lsi->containsIntersections() ) { osg::Vec3d isect = _lsi->getIntersections().begin()->getWorldIntersectPoint(); // transform back to input SRS: GeoPoint output; output.fromWorld( point.getSRS(), isect ); out_elevation = (float)output.z(); if ( out_actualResolution ) *out_actualResolution = 0.0; return true; } } else { //OE_INFO << LC << "Trivial rejection (bounds check)" << std::endl; } } } } if (_elevationLayers.empty()) { // this means there are no heightfields. out_elevation = NO_DATA_VALUE; return true; } // secure map pointer: osg::ref_ptr<const Map> map; if (!_map.lock(map)) { return false; } // tile size (resolution of elevation tiles) unsigned tileSize = 257; // yes? // default LOD: unsigned lod = 23u; // attempt to map the requested resolution to an LOD: if (desiredResolution > 0.0) { int level = map->getProfile()->getLevelOfDetailForHorizResolution(desiredResolution, tileSize); if ( level > 0 ) lod = level; } // do we need a new ElevationEnvelope? if (!_envelope.valid() || !point.getSRS()->isHorizEquivalentTo(_envelope->getSRS()) || lod != _envelope->getLOD()) { _envelope = map->getElevationPool()->createEnvelope(point.getSRS(), lod); } // sample the elevation, and if requested, the resolution as well: if (out_actualResolution) { std::pair<float, float> result = _envelope->getElevationAndResolution(point.x(), point.y()); out_elevation = result.first; *out_actualResolution = result.second; } else { out_elevation = _envelope->getElevation(point.x(), point.y()); } return out_elevation != NO_DATA_VALUE; }
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; }