void LineOfSightTether::operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { LinearLineOfSightNode* los = static_cast<LinearLineOfSightNode*>(node); if ( los->getMapNode() ) { if (_startNode.valid()) { osg::Vec3d worldStart = getNodeCenter(_startNode); //Convert to mappoint since that is what LOS expects GeoPoint mapStart; mapStart.fromWorld( los->getMapNode()->getMapSRS(), worldStart ); los->setStart( mapStart ); //.vec3d() ); } if (_endNode.valid()) { osg::Vec3d worldEnd = getNodeCenter( _endNode ); //Convert to mappoint since that is what LOS expects GeoPoint mapEnd; mapEnd.fromWorld( los->getMapNode()->getMapSRS(), worldEnd ); los->setEnd( mapEnd ); //.vec3d() ); } } } traverse(node, nv); }
void LineOfSightEditor::updateDraggers() { osg::Vec3d start = _los->getStartWorld(); GeoPoint startMap; startMap.fromWorld(_los->getMapNode()->getMapSRS(), start); _startDragger->setPosition( startMap, false ); osg::Vec3d end = _los->getEndWorld(); GeoPoint endMap; endMap.fromWorld(_los->getMapNode()->getMapSRS(), end); _endDragger->setPosition( endMap, false ); }
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 ); } }
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { if (ea.getEventType() == ea.PUSH && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { osg::Vec3d world; if ( _mapNode->getTerrain()->getWorldCoordsUnderMouse( aa.asView(), ea.getX(), ea.getY(), world )) { GeoPoint mapPoint; mapPoint.fromWorld( _mapNode->getMapSRS(), world ); //_mapNode->getMap()->worldPointToMapPoint( world, mapPoint ); if (!_startValid) { _startValid = true; _start = mapPoint.vec3d(); if (_featureNode.valid()) { _root->removeChild( _featureNode.get() ); _featureNode = 0; } } else { _end = mapPoint.vec3d(); compute(); _startValid = false; } } } return false; }
bool AddPointHandler::addPoint( float x, float y, osgViewer::View* view ) { osg::Vec3d world; MapNode* mapNode = _featureNode->getMapNode(); if ( mapNode->getTerrain()->getWorldCoordsUnderMouse( view, x, y, world ) ) { // Get the map point from the world GeoPoint mapPoint; mapPoint.fromWorld( mapNode->getMapSRS(), world ); Feature* feature = _featureNode->getFeature(); if ( feature ) { // Convert the map point to the feature's SRS GeoPoint featurePoint = mapPoint.transform( feature->getSRS() ); feature->getGeometry()->push_back( featurePoint.vec3d() ); _featureNode->init(); return true; } } return false; }
void RadialLineOfSightEditor::updateDraggers() { osg::Vec3d center = _los->getCenterWorld(); GeoPoint centerMap; centerMap.fromWorld(_los->getMapNode()->getMapSRS(), center); _dragger->setPosition(centerMap, false); }
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 ); } }
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 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( s_mapNode->getMapSRS(), world ); // Depending on the level of detail key you request, you will get a mesh that should line up exactly with the highest resolution mesh that the terrain engine will draw. // At level 15 that is a 257x257 heightfield. If you select a higher lod, the mesh will be less dense. TileKey key = s_mapNode->getMap()->getProfile()->createTileKey(mapPoint.x(), mapPoint.y(), 15); OE_NOTICE << "Creating tile " << key.str() << std::endl; osg::ref_ptr<osg::Node> node = s_mapNode->getTerrainEngine()->createTile(key); if (node.valid()) { // Extract the triangles from the node that was created and do our own rendering. Simulates what you would do when passing in the triangles to a physics engine. OE_NOTICE << "Created tile for " << key.str() << std::endl; CollectTrianglesVisitor v; node->accept(v); node = v.buildNode(); if (_node.valid()) { s_root->removeChild( _node.get() ); } osg::Group* group = new osg::Group; // Show the actual mesh. group->addChild( node.get() ); _node = group; // Clamp the marker to the intersection of the triangles created by osgEarth. This should line up with the mesh that is actually rendered. double z = 0.0; s_mapNode->getTerrain()->getHeight( node, s_mapNode->getMapSRS(), mapPoint.x(), mapPoint.y(), &z); GeoTransform* xform = new GeoTransform(); xform->setPosition( osgEarth::GeoPoint(s_mapNode->getMapSRS(),mapPoint.x(), mapPoint.y(), z, ALTMODE_ABSOLUTE) ); xform->addChild( marker.get() ); group->addChild( xform ); s_root->addChild( _node.get() ); } else { OE_NOTICE << "Failed to create tile for " << key.str() << std::endl; } } }
void ClipSpace::clampToLeft(GeoPoint& p) { p.transformInPlace(p.getSRS()->getGeographicSRS()); osg::Vec3d world; p.toWorld(world); osg::Vec3d clip = world * _worldToClip; clip.x() = -1.0; world = clip * _clipToWorld; p.fromWorld(p.getSRS(), world); }
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 handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*) { if (ea.getEventType() == ea.KEYDOWN && ea.getKey() == _c) { osg::Vec3d world; _mapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), world); GeoPoint coords; coords.fromWorld(s_activeMap->getSRS(), world); osg::ref_ptr<ElevationEnvelope> env = s_activeMap->getElevationPool()->createEnvelope(s_activeMap->getSRS(), 23u); float ep_elev = env->getElevation(coords.x(), coords.y()); OE_NOTICE << "Elevations under mouse. EP=" << ep_elev << "\n"; } return false; }
void update(double time) { double angle = (time / _time); angle = (angle - (int)angle) * osg::PI * 2.0; osg::Quat quat(angle, _up ); osg::Vec3d spoke = quat * (_side * _radius); osg::Vec3d end = _center + spoke; GeoPoint mapPos; mapPos.fromWorld( _mapNode->getMapSRS(), end ); //_mapNode->getMap()->worldPointToMapPoint(end, mapPos); _track->setPosition(mapPos); }
osg::BoundingSphere LocalGeometryNode::computeBound() const { osg::BoundingSphere bs = AnnotationNode::computeBound(); // NOTE: this is the same code found in Feature.cpp. Consolidate? _boundingPT.clear(); // add planes for the four sides of the BS. Normals point inwards. _boundingPT.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) ); _boundingPT.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) ); _boundingPT.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) ); _boundingPT.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0, bs.radius(),0)) ); const SpatialReference* srs = getPosition().getSRS(); if ( srs ) { // for a projected feature, we're done. For a geocentric one, transform the polytope // into world (ECEF) space. if ( srs->isGeographic() && !srs->isPlateCarre() ) { const osg::EllipsoidModel* e = srs->getEllipsoid(); // add a bottom cap, unless the bounds are sufficiently large. double minRad = std::min(e->getRadiusPolar(), e->getRadiusEquator()); double maxRad = std::max(e->getRadiusPolar(), e->getRadiusEquator()); double zeroOffset = bs.center().length(); if ( zeroOffset > minRad * 0.1 ) { _boundingPT.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) ); } } // transform the clipping planes ito ECEF space GeoPoint refPoint; refPoint.fromWorld( srs, bs.center() ); osg::Matrix local2world; refPoint.createLocalToWorld( local2world ); _boundingPT.transform( local2world ); } return bs; }
void RadialLineOfSightTether::operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { RadialLineOfSightNode* los = static_cast<RadialLineOfSightNode*>(node); osg::Vec3d worldCenter = getNodeCenter( _node ); //Convert center to mappoint since that is what LOS expects GeoPoint mapCenter; mapCenter.fromWorld( los->getMapNode()->getMapSRS(), worldCenter ); //los->getMapNode()->getMap()->worldPointToMapPoint( worldCenter, mapCenter ); los->setCenter( mapCenter.vec3d() ); } traverse(node, nv); }
bool Feature::getWorldBoundingPolytope(const SpatialReference* srs, osg::Polytope& out_polytope) const { osg::BoundingSphered bs; if ( getWorldBound(srs, bs) && bs.valid() ) { out_polytope.clear(); // add planes for the four sides of the BS. Normals point inwards. out_polytope.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) ); out_polytope.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) ); out_polytope.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) ); out_polytope.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0, bs.radius(),0)) ); // for a projected feature, we're done. For a geocentric one, transform the polytope // into world (ECEF) space. if ( srs->isGeographic() && !srs->isPlateCarre() ) { const osg::EllipsoidModel* e = srs->getEllipsoid(); // add a bottom cap, unless the bounds are sufficiently large. double minRad = std::min(e->getRadiusPolar(), e->getRadiusEquator()); double maxRad = std::max(e->getRadiusPolar(), e->getRadiusEquator()); double zeroOffset = bs.center().length(); if ( zeroOffset > minRad * 0.1 ) { out_polytope.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) ); } } // transform the clipping planes ito ECEF space GeoPoint refPoint; refPoint.fromWorld( srs, bs.center() ); osg::Matrix local2world; refPoint.createLocalToWorld( local2world ); out_polytope.transform( local2world ); return true; } return false; }
bool MouseCoordsTool::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { if (ea.getEventType() == ea.MOVE || ea.getEventType() == ea.DRAG) { osg::Vec3d world; if ( _mapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), world) ) { GeoPoint map; map.fromWorld( _mapNode->getMapSRS(), world ); for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->set( map, aa.asView(), _mapNode ); } else { for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->reset( aa.asView(), _mapNode ); } #if 1 // testing AGL, Dist to Point osg::Vec3d eye, center, up; aa.asView()->getCamera()->getViewMatrixAsLookAt(eye, center, up); DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector(eye, osg::Vec3d(0,0,0)); osgUtil::IntersectionVisitor iv(lsi); lsi->setIntersectionLimit(lsi->LIMIT_NEAREST); //iv.setUserData( new Map() ); _mapNode->accept(iv); if ( !lsi->getIntersections().empty() ) { double agl = (eye - lsi->getFirstIntersection().getWorldIntersectPoint()).length(); double dtp = (eye - world).length(); //OE_NOTICE << "AGL = " << agl << "m; DPT = " << dtp << "m" << std::endl; Registry::instance()->startActivity("AGL", Stringify() << agl << " m"); Registry::instance()->startActivity("Range", Stringify() << dtp << " m"); } #endif } return false; }
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(output.vec3d(), 0.0, -90.0, 1e5), *_views)); } } }
void CircleNodeEditor::computeBearing() { _bearing = osg::DegreesToRadians( 90.0 ); //Get the radius dragger's position if (!_radiusDragger->getMatrix().isIdentity()) { // Get the current location of the center of the circle (in lat/long) GeoPoint location = _node->getPosition(); location.makeGeographic(); // location of the radius dragger (in lat/long) GeoPoint radiusLocation; radiusLocation.fromWorld( location.getSRS(), _radiusDragger->getMatrix().getTrans() ); // calculate the bearing b/w the _bearing = GeoMath::bearing( osg::DegreesToRadians(location.y()), osg::DegreesToRadians(location.x()), osg::DegreesToRadians(radiusLocation.y()), osg::DegreesToRadians(radiusLocation.x())); } }
bool MouseCoordsTool::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { if (ea.getEventType() == ea.MOVE || ea.getEventType() == ea.DRAG) { osg::Vec3d world; if ( _mapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), world) ) { GeoPoint map; map.fromWorld( _mapNode->getMapSRS(), world ); for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->set( map, aa.asView(), _mapNode ); } else { for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->reset( aa.asView(), _mapNode ); } } 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( s_mapNode->getMapSRS(), world ); TileKey key = s_mapNode->getMap()->getProfile()->createTileKey(mapPoint.x(), mapPoint.y(), 13); OE_NOTICE << "Creating tile " << key.str() << std::endl; osg::ref_ptr<osg::Node> node = s_mapNode->getTerrainEngine()->createTile(key); if (node.valid()) { OE_NOTICE << "Created tile for " << key.str() << std::endl; CollectTrianglesVisitor v; node->accept(v); osg::ref_ptr<osg::Node> output = v.buildNode(); osgDB::writeNodeFile( *output.get(), "createtile.osgt" ); OE_NOTICE << "Wrote tile to createtile.osgt\n"; //osgDB::writeNodeFile(v.buildNode( //s_root->addChild(v.buildNode()); } else { OE_NOTICE << "Failed to create tile for " << key.str() << std::endl; } } }
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 OverlayNode::traverse( osg::NodeVisitor& nv ) { if ( !_overlayProxyContainer.valid() ) { osg::Group::traverse( nv ); } else { if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR ) { if ( _active ) { // do nothing -- culling will happen via the OverlayProxy instead. } else { // for a non-active node, just traverse children as usual. osg::Group::traverse( nv ); } } else if ( nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR ) { if ( _dirty ) { applyChanges(); _dirty = false; ADJUST_UPDATE_TRAV_COUNT( this, -1 ); } // traverse children directly, regardles of active status osg::Group::traverse( nv ); } else if (dynamic_cast<osgUtil::IntersectionVisitor*>(&nv)) { /* In order to properly intersect with overlay geometries, attempt to find the point on the terrain where the pick occurred cast a second intersector vertically at that point. Currently this is only imlpemented for our custom PrimitiveIntersector. */ osgUtil::IntersectionVisitor* iv = dynamic_cast<osgUtil::IntersectionVisitor*>(&nv); osgEarth::PrimitiveIntersector* pi = dynamic_cast<osgEarth::PrimitiveIntersector *>(iv->getIntersector()); osg::ref_ptr<MapNode> mapNode; if (pi && !pi->getOverlayIgnore() && _mapNode.lock(mapNode)) { osg::NodePath path = iv->getNodePath(); osg::NodePath prunedNodePath( path.begin(), path.end()-1 ); osg::Matrix modelToWorld = osg::computeLocalToWorld(prunedNodePath); osg::Vec3d worldStart = pi->getStart() * modelToWorld; osg::Vec3d worldEnd = pi->getEnd() * modelToWorld; osg::ref_ptr<DPLineSegmentIntersector> lsi = new DPLineSegmentIntersector(worldStart, worldEnd); osgUtil::IntersectionVisitor ivTerrain(lsi.get()); mapNode->getTerrainEngine()->accept(ivTerrain); if (lsi->containsIntersections()) { osg::Vec3d worldIntersect = lsi->getFirstIntersection().getWorldIntersectPoint(); GeoPoint mapIntersect; mapIntersect.fromWorld(mapNode->getMapSRS(), worldIntersect); osg::Vec3d newMapStart(mapIntersect.x(), mapIntersect.y(), 25000.0); osg::Vec3d newMapEnd(mapIntersect.x(), mapIntersect.y(), -25000.0); osg::Vec3d newWorldStart; mapNode->getMapSRS()->transformToWorld(newMapStart, newWorldStart); osg::Vec3d newWorldEnd; mapNode->getMapSRS()->transformToWorld(newMapEnd, newWorldEnd); osg::Matrix worldToModel; worldToModel.invert(modelToWorld); osg::Vec3d newModelStart = newWorldStart * worldToModel; osg::Vec3d newModelEnd = newWorldEnd * worldToModel; osg::ref_ptr<osgEarth::PrimitiveIntersector> pi2 = new osgEarth::PrimitiveIntersector(osgUtil::Intersector::MODEL, newModelStart, newModelEnd, pi->getThickness(), true); osgUtil::IntersectionVisitor iv2(pi2); iv2.setTraversalMask(iv->getTraversalMask()); path[0]->accept(iv2); if (pi2->containsIntersections()) { // Insert newlly found intersections into the original intersector. for (PrimitiveIntersector::Intersections::iterator it = pi2->getIntersections().begin(); it != pi2->getIntersections().end(); ++it) { PrimitiveIntersector::Intersection intersection(*it); intersection.ratio = 1.0; pi->insertIntersection(intersection); } } } else { //OE_WARN << LC << "No hits on terrain!" << std::endl; } } else { osg::Group::traverse( nv ); } } // handle other visitor types (like intersections, etc) by simply // traversing the child graph. else // if ( nv.getNodeVisitor() == osg::NodeVisitor::NODE_VISITOR ) { osg::Group::traverse( nv ); } } }
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( "-" ); } }
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 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; aa.requestRedraw(); return true; } } else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) { _dragging = false; aa.requestRedraw(); } else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) { if (_dragging) { osg::Vec3d world; if ( _mapNode->getTerrain()->getWorldCoordsUnderMouse(view, ea.getX(), ea.getY(), world) ) { //Get the absolute mapPoint that they've drug it to. GeoPoint mapPoint; mapPoint.fromWorld( _mapNode->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; }
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; }
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 ); } }
void MapNode::traverse( osg::NodeVisitor& nv ) { if ( nv.getVisitorType() == nv.EVENT_VISITOR ) { unsigned int numBlacklist = Registry::instance()->getNumBlacklistedFilenames(); if (numBlacklist != _lastNumBlacklistedFilenames) { //Only remove the blacklisted filenames if new filenames have been added since last time. _lastNumBlacklistedFilenames = numBlacklist; RemoveBlacklistedFilenamesVisitor v; _terrainEngine->accept( v ); } // traverse: std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); } else if ( nv.getVisitorType() == nv.CULL_VISITOR ) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); if ( cv ) { // insert traversal data for this camera: osg::ref_ptr<osg::Referenced> oldUserData = cv->getUserData(); MapNodeCullData* cullData = getCullData( cv->getCurrentCamera() ); cv->setUserData( cullData ); cullData->_mapNode = this; // calculate altitude: osg::Vec3d eye = cv->getViewPoint(); const SpatialReference* srs = getMapSRS(); if ( srs && !srs->isProjected() ) { GeoPoint ecef; ecef.fromWorld( srs, eye ); cullData->_cameraAltitude = ecef.alt(); } else { cullData->_cameraAltitude = eye.z(); } // window scale matrix: osg::Matrix m4 = cv->getWindowMatrix(); osg::Matrix3 m3( m4(0,0), m4(1,0), m4(2,0), m4(0,1), m4(1,1), m4(2,1), m4(0,2), m4(1,2), m4(2,2) ); cullData->_windowScaleMatrix->set( m3 ); // traverse: cv->pushStateSet( cullData->_stateSet.get() ); std::for_each( _children.begin(), _children.end(), osg::NodeAcceptOp(nv) ); cv->popStateSet(); // restore: cv->setUserData( oldUserData.get() ); } } else { osg::Group::traverse( nv ); } }