osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthUtil/MeasureTool.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00020 #include <osgEarthUtil/MeasureTool>
00021 #include <osgEarth/GeoMath>
00022 
00023 #include <osgEarthFeatures/Feature>
00024 
00025 using namespace osgEarth;
00026 using namespace osgEarth::Util;
00027 using namespace osgEarth::Symbology;
00028 using namespace osgEarth::Features;
00029 
00030 
00031 
00032 
00033 MeasureToolHandler::MeasureToolHandler( osg::Group* group, osgEarth::MapNode* mapNode ):
00034 _mouseDown(false),
00035 _group(group),
00036 _gotFirstLocation(false),
00037 _lastPointTemporary(false),
00038 _finished(false),
00039 _geoInterpolation( GEOINTERP_GREAT_CIRCLE ),
00040 _mouseButton( osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON),
00041 _isPath( false ),
00042 _mapNode( mapNode ),
00043 _intersectionMask(0xffffffff)
00044 {
00045     LineString* line = new LineString();
00046     _feature = new Feature();
00047     _feature->setGeometry( line );
00048     _feature->geoInterp() = _geoInterpolation;    
00049 
00050     //Define a style for the line
00051     Style style;
00052     LineSymbol* ls = style.getOrCreateSymbol<LineSymbol>();
00053     ls->stroke()->color() = osg::Vec4f( 1,0,0,1 );
00054     ls->stroke()->width() = 2.0f;   
00055 
00056     _feature->style() = style;
00057 
00058     _featureNode = new FeatureNode( _mapNode.get(), _feature.get(), false);
00059     
00060 
00061     //Disable lighting and depth testing for the feature graph
00062     _featureNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
00063     _featureNode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
00064 
00065     _group->addChild (_featureNode.get() );
00066 }
00067 
00068 MeasureToolHandler::~MeasureToolHandler()
00069 {
00070     if (_group.valid()) _group->removeChild( _featureNode.get() );
00071 }
00072 
00073 bool
00074 MeasureToolHandler::getIsPath() const
00075 {
00076     return _isPath;
00077 }
00078 
00079 void
00080 MeasureToolHandler::setIsPath( bool path ) 
00081 {
00082     if (_isPath != path)
00083     {
00084         _isPath = path;
00085         _finished = true;
00086         clear();                    
00087         _gotFirstLocation = false;
00088     }
00089 }
00090 
00091 
00092 GeoInterpolation
00093 MeasureToolHandler::getGeoInterpolation() const
00094 {
00095     return _geoInterpolation;
00096 }
00097 
00098 void
00099 MeasureToolHandler::setGeoInterpolation( GeoInterpolation geoInterpolation )
00100 {
00101     if (_geoInterpolation != geoInterpolation)
00102     {
00103         _geoInterpolation = geoInterpolation;
00104         _feature->geoInterp() = _geoInterpolation;
00105         _featureNode->init();
00106         fireDistanceChanged();
00107     }
00108 }
00109 
00110 void
00111 MeasureToolHandler::setLineStyle( const Style& style )
00112 {
00113      _feature->style() = style;
00114      _featureNode->init();
00115 }
00116 
00117 
00118 bool MeasureToolHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
00119 {    
00120     if ( ea.getHandled() )
00121     {
00122         return false;
00123     }
00124 
00125     
00126     osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());                
00127     if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == _mouseButton)
00128     {        
00129         _mouseDown = true;
00130         _mouseDownX = ea.getX();
00131         _mouseDownY = ea.getY();
00132     }
00133     else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == _mouseButton)
00134     {        
00135         float eps = 1.0f;
00136         _mouseDown = false;
00137         if (osg::equivalent(ea.getX(), _mouseDownX) && osg::equivalent(ea.getY(), _mouseDownY))
00138         {
00139             double lon, lat;
00140             if (getLocationAt(view, ea.getX(), ea.getY(), lon, lat))
00141             {
00142                 if (!_gotFirstLocation)
00143                 {
00144                     _finished = false;
00145                     clear();                    
00146                     _gotFirstLocation = true;
00147                     _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );
00148                 }
00149                 else
00150                 {
00151                     if (_lastPointTemporary)
00152                     {
00153                         _feature->getGeometry()->back() = osg::Vec3d( lon, lat, 0 );
00154                         _lastPointTemporary = false;
00155                     }
00156                     else
00157                     {                     
00158                         _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );
00159                     }
00160                     _featureNode->init();
00161                     //_gotFirstLocation = false;
00162                     //_finished = true;
00163                     if (_finished || !_isPath) {
00164                         _gotFirstLocation = false;
00165                     }
00166                     fireDistanceChanged();
00167                 }
00168             }
00169         }
00170     }  
00171     else if (ea.getEventType() == osgGA::GUIEventAdapter::DOUBLECLICK) {        
00172         if (_gotFirstLocation)
00173         {
00174             //_gotFirstLocation = false;
00175             _finished = true;     
00176             return true;
00177         }
00178     }
00179     else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE)
00180     {
00181         if (_gotFirstLocation)
00182         {
00183             double lon, lat;
00184             if (getLocationAt(view, ea.getX(), ea.getY(), lon, lat))
00185             {
00186                 if (!_lastPointTemporary)
00187                 {
00188                     _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );                 
00189                     _lastPointTemporary = true;
00190                 }                        
00191                 else
00192                 {
00193                     _feature->getGeometry()->back() = osg::Vec3d( lon, lat, 0 );
00194                 }
00195                 _featureNode->init();
00196                 fireDistanceChanged();
00197             }
00198         }
00199     }    
00200     return false;
00201 }
00202 
00203 bool MeasureToolHandler::getLocationAt(osgViewer::View* view, double x, double y, double &lon, double &lat)
00204 {
00205     osgUtil::LineSegmentIntersector::Intersections results;            
00206     if ( view->computeIntersections( x, y, results, _intersectionMask ) )
00207     {
00208         // find the first hit under the mouse:
00209         osgUtil::LineSegmentIntersector::Intersection first = *(results.begin());
00210         osg::Vec3d point = first.getWorldIntersectPoint();
00211 
00212         double lat_rad, lon_rad, height;       
00213         _mapNode->getMap()->getProfile()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight( point.x(), point.y(), point.z(), lat_rad, lon_rad, height );
00214         lat = osg::RadiansToDegrees( lat_rad );
00215         lon = osg::RadiansToDegrees( lon_rad );
00216         return true;
00217     }
00218     return false;
00219 }
00220 
00221 void MeasureToolHandler::clear()
00222 {
00223     //Clear the locations    
00224     _feature->getGeometry()->clear();
00225     //_features->dirty();
00226     _featureNode->init();
00227     fireDistanceChanged();
00228 
00229     _gotFirstLocation = false; 
00230     _lastPointTemporary = false; 
00231 }
00232 
00233 void
00234 MeasureToolHandler::setMouseButton(int mouseButton)
00235 {
00236     _mouseButton = mouseButton;
00237 }
00238 
00239 int
00240 MeasureToolHandler::getMouseButton() const
00241 {
00242     return _mouseButton;
00243 }
00244 
00245 
00246 void MeasureToolHandler::addEventHandler(MeasureToolEventHandler* handler )
00247 {
00248     _eventHandlers.push_back( handler );
00249 }
00250 
00251 
00252 void MeasureToolHandler::fireDistanceChanged()
00253 {
00254     double distance = 0;
00255     if (_geoInterpolation == GEOINTERP_GREAT_CIRCLE)
00256     {
00257         distance = GeoMath::distance(_feature->getGeometry()->asVector());
00258     }
00259     else if (_geoInterpolation == GEOINTERP_RHUMB_LINE) 
00260     {
00261         distance = GeoMath::rhumbDistance(_feature->getGeometry()->asVector());
00262     }
00263     for (MeasureToolEventHandlerList::const_iterator i = _eventHandlers.begin(); i != _eventHandlers.end(); ++i)
00264     {
00265         i->get()->onDistanceChanged( this, distance );
00266     }
00267 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines