osgEarth 2.1.1
|
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/FeatureEditing> 00021 #include <osgEarthUtil/Draggers> 00022 00023 using namespace osgEarth::Util; 00024 using namespace osgEarth::Symbology; 00025 using namespace osgEarth::Features; 00026 00027 /****************************************************************/ 00028 AddPointHandler::AddPointHandler(Feature* feature, FeatureListSource* source, const osgEarth::SpatialReference* mapSRS): 00029 _feature(feature), 00030 _source( source ), 00031 _mapSRS( mapSRS ), 00032 _mouseDown( false ), 00033 _firstMove( false ), 00034 _mouseButton( osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ), 00035 _intersectionMask( 0xffffffff ) 00036 { 00037 } 00038 00039 void 00040 AddPointHandler::setMouseButton( osgGA::GUIEventAdapter::MouseButtonMask mouseButton) 00041 { 00042 _mouseButton = mouseButton; 00043 } 00044 00045 osgGA::GUIEventAdapter::MouseButtonMask 00046 AddPointHandler::getMouseButton() const 00047 { 00048 return _mouseButton; 00049 } 00050 00051 bool 00052 AddPointHandler::addPoint( float x, float y, osgViewer::View* view ) 00053 { 00054 osgUtil::LineSegmentIntersector::Intersections results; 00055 if ( view->computeIntersections( x, y, results, _intersectionMask ) ) 00056 { 00057 // find the first hit under the mouse: 00058 osgUtil::LineSegmentIntersector::Intersection first = *(results.begin()); 00059 osg::Vec3d point = first.getWorldIntersectPoint(); 00060 00061 // transform it to map coordinates: 00062 double lat_rad, lon_rad, dummy; 00063 _mapSRS->getEllipsoid()->convertXYZToLatLongHeight( point.x(), point.y(), point.z(), lat_rad, lon_rad, dummy ); 00064 00065 double lat_deg = osg::RadiansToDegrees( lat_rad ); 00066 double lon_deg = osg::RadiansToDegrees( lon_rad ); 00067 00068 if (_feature.valid()) 00069 { 00070 _feature->getGeometry()->push_back( osg::Vec3d(lon_deg, lat_deg, 0) ); 00071 _source->dirty(); 00072 } 00073 return true; 00074 } 00075 return false; 00076 } 00077 00078 bool 00079 AddPointHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) 00080 { 00081 osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView()); 00082 if ( ea.getEventType() == osgGA::GUIEventAdapter::PUSH ) 00083 { 00084 if (ea.getButton() == _mouseButton) 00085 { 00086 _mouseDown = true; 00087 _firstMove = true; 00088 return addPoint( ea.getX(), ea.getY(), view ); 00089 } 00090 } 00091 else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) 00092 { 00093 if (ea.getButton() == _mouseButton) 00094 { 00095 _mouseDown = false; 00096 } 00097 } 00098 else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE || ea.getEventType() == osgGA::GUIEventAdapter::DRAG) 00099 { 00100 if (_mouseDown) 00101 { 00102 if (!_firstMove) 00103 { 00104 return addPoint( ea.getX(), ea.getY(), view ); 00105 } 00106 _firstMove = false; 00107 } 00108 return true; 00109 } 00110 00111 return false; 00112 } 00113 00114 /****************************************************************/ 00115 00116 class MoveFeatureDraggerCallback : public osgManipulator::DraggerCallback 00117 { 00118 public: 00119 MoveFeatureDraggerCallback(Feature* feature, FeatureSource* source, const Map* map, int point): 00120 _feature(feature), 00121 _source(source), 00122 _map(map), 00123 _point(point) 00124 {} 00125 00126 osg::Vec2d getLocation(const osg::Matrixd& matrix) 00127 { 00128 osg::Vec3d trans = matrix.getTrans(); 00129 double lat, lon, height; 00130 _map->getProfile()->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(trans.x(), trans.y(), trans.z(), lat, lon, height); 00131 return osg::Vec2d(osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat)); 00132 } 00133 00134 00135 virtual bool receive(const osgManipulator::MotionCommand& command) 00136 { 00137 switch (command.getStage()) 00138 { 00139 case osgManipulator::MotionCommand::START: 00140 { 00141 // Save the current matrix 00142 osg::Vec3d startLocation = (*_feature->getGeometry())[_point]; 00143 double x, y, z; 00144 _map->getProfile()->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(osg::DegreesToRadians(startLocation.y()), osg::DegreesToRadians(startLocation.x()), 0, x, y, z); 00145 _startMotionMatrix = osg::Matrixd::translate(x, y, z); 00146 00147 // Get the LocalToWorld and WorldToLocal matrix for this node. 00148 osg::NodePath nodePathToRoot; 00149 _localToWorld = osg::Matrixd::identity(); 00150 _worldToLocal = osg::Matrixd::identity(); 00151 00152 return true; 00153 } 00154 case osgManipulator::MotionCommand::MOVE: 00155 { 00156 // Transform the command's motion matrix into local motion matrix. 00157 osg::Matrix localMotionMatrix = _localToWorld * command.getWorldToLocal() 00158 * command.getMotionMatrix() 00159 * command.getLocalToWorld() * _worldToLocal; 00160 00161 osg::Matrixd newMatrix = localMotionMatrix * _startMotionMatrix; 00162 osg::Vec2d location = getLocation( newMatrix ); 00163 (*_feature->getGeometry())[_point] = osg::Vec3d(location.x(), location.y(), 0); 00164 _source->dirty(); 00165 00166 return true; 00167 } 00168 case osgManipulator::MotionCommand::FINISH: 00169 { 00170 return true; 00171 } 00172 case osgManipulator::MotionCommand::NONE: 00173 default: 00174 return false; 00175 } 00176 } 00177 00178 00179 osg::ref_ptr<const Map> _map; 00180 osg::ref_ptr< Feature > _feature; 00181 osg::ref_ptr< FeatureSource > _source; 00182 00183 osg::Matrix _startMotionMatrix; 00184 int _point; 00185 00186 osg::Matrix _localToWorld; 00187 osg::Matrix _worldToLocal; 00188 }; 00189 00190 /****************************************************************/ 00191 FeatureEditor::FeatureEditor( Feature* feature, FeatureSource* source, MapNode* mapNode ): 00192 _feature( feature ), 00193 _source( source ), 00194 _mapNode( mapNode ), 00195 _color(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), 00196 _pickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)), 00197 _size( 5.0f ) 00198 { 00199 init(); 00200 } 00201 00202 00203 const osg::Vec4f& 00204 FeatureEditor::getPickColor() const 00205 { 00206 return _pickColor; 00207 } 00208 00209 void 00210 FeatureEditor::setPickColor( const osg::Vec4f& pickColor ) 00211 { 00212 if (_pickColor != pickColor) 00213 { 00214 _pickColor = pickColor; 00215 init(); 00216 } 00217 } 00218 00219 const osg::Vec4f& 00220 FeatureEditor::getColor() const 00221 { 00222 return _color; 00223 } 00224 00225 void 00226 FeatureEditor::setColor( const osg::Vec4f& color ) 00227 { 00228 if (_color != color) 00229 { 00230 _color = color; 00231 init(); 00232 } 00233 } 00234 00235 float 00236 FeatureEditor::getSize() const 00237 { 00238 return _size; 00239 } 00240 00241 void 00242 FeatureEditor::setSize( float size ) 00243 { 00244 if (_size != size) 00245 { 00246 _size = size; 00247 init(); 00248 } 00249 } 00250 00251 void 00252 FeatureEditor::init() 00253 { 00254 removeChildren( 0, this->getNumChildren() ); 00255 //Create a dragger for each point 00256 for (unsigned int i = 0; i < _feature->getGeometry()->size(); i++) 00257 { 00258 osg::Matrixd matrix; 00259 double lat = (*_feature->getGeometry())[i].y(); 00260 double lon = (*_feature->getGeometry())[i].x(); 00261 _mapNode->getMap()->getProfile()->getSRS()->getEllipsoid()->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(lat), osg::DegreesToRadians(lon), 0, matrix); 00262 00263 IntersectingDragger* dragger = new IntersectingDragger; 00264 dragger->setColor( _color ); 00265 dragger->setPickColor( _pickColor ); 00266 dragger->setSize( _size ); 00267 dragger->setNode( _mapNode->getTerrainEngine() ); 00268 dragger->setupDefaultGeometry(); 00269 dragger->setMatrix(matrix); 00270 dragger->setHandleEvents( true ); 00271 dragger->addDraggerCallback(new MoveFeatureDraggerCallback(_feature.get(), _source.get(), _mapNode->getMap(), i) ); 00272 00273 addChild(dragger); 00274 } 00275 }