osgEarth 2.1.1
|
00001 #include <osgEarthUtil/ImageOverlayEditor> 00002 00003 #include <osg/Geode> 00004 #include <osg/io_utils> 00005 #include <osg/AutoTransform> 00006 #include <osg/ShapeDrawable> 00007 #include <osgViewer/Viewer> 00008 00009 using namespace osgEarth; 00010 using namespace osgEarth::Util; 00011 00012 /***************************************************************************/ 00013 00014 class ImageOverlayDraggerCallback : public osgManipulator::DraggerCallback 00015 { 00016 public: 00017 ImageOverlayDraggerCallback(ImageOverlay* overlay, const osg::EllipsoidModel* ellipsoid, ImageOverlay::ControlPoint controlPoint): 00018 _overlay(overlay), 00019 _ellipsoid(ellipsoid), 00020 _controlPoint(controlPoint) 00021 {} 00022 00023 osg::Vec2d getLocation(const osg::Matrixd& matrix) 00024 { 00025 osg::Vec3d trans = matrix.getTrans(); 00026 double lat, lon, height; 00027 _ellipsoid->convertXYZToLatLongHeight(trans.x(), trans.y(), trans.z(), lat, lon, height); 00028 return osg::Vec2d(osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat)); 00029 } 00030 00031 00032 virtual bool receive(const osgManipulator::MotionCommand& command) 00033 { 00034 switch (command.getStage()) 00035 { 00036 case osgManipulator::MotionCommand::START: 00037 { 00038 // Save the current matrix 00039 osg::Vec2d startLocation = _overlay->getControlPoint(_controlPoint); 00040 double x, y, z; 00041 _ellipsoid->convertLatLongHeightToXYZ(osg::DegreesToRadians(startLocation.y()), osg::DegreesToRadians(startLocation.x()), 0, x, y, z); 00042 _startMotionMatrix = osg::Matrixd::translate(x, y, z); 00043 00044 // Get the LocalToWorld and WorldToLocal matrix for this node. 00045 osg::NodePath nodePathToRoot; 00046 _localToWorld = osg::Matrixd::identity(); 00047 _worldToLocal = osg::Matrixd::identity(); 00048 00049 return true; 00050 } 00051 case osgManipulator::MotionCommand::MOVE: 00052 { 00053 // Transform the command's motion matrix into local motion matrix. 00054 osg::Matrix localMotionMatrix = _localToWorld * command.getWorldToLocal() 00055 * command.getMotionMatrix() 00056 * command.getLocalToWorld() * _worldToLocal; 00057 00058 osg::Matrixd newMatrix = localMotionMatrix * _startMotionMatrix; 00059 osg::Vec2d location = getLocation( newMatrix ); 00060 _overlay->setControlPoint(_controlPoint, location.x(), location.y()); 00061 00062 return true; 00063 } 00064 case osgManipulator::MotionCommand::FINISH: 00065 { 00066 return true; 00067 } 00068 case osgManipulator::MotionCommand::NONE: 00069 default: 00070 return false; 00071 } 00072 } 00073 00074 00075 osg::ref_ptr<const osg::EllipsoidModel> _ellipsoid; 00076 osg::ref_ptr<ImageOverlay> _overlay; 00077 00078 osg::Matrix _startMotionMatrix; 00079 ImageOverlay::ControlPoint _controlPoint; 00080 00081 osg::Matrix _localToWorld; 00082 osg::Matrix _worldToLocal; 00083 }; 00084 00085 /***************************************************************************/ 00086 /*class UpdateDraggersCallback : public osgManipulator::DraggerCallback 00087 { 00088 public: 00089 UpdateDraggersCallback(ImageOverlayEditor* editor) 00090 { 00091 _editor = editor; 00092 } 00093 00094 virtual bool receive(const osgManipulator::MotionCommand& command) 00095 { 00096 _editor->updateDraggers(); 00097 return false; 00098 } 00099 00100 friend class ImageOverlayEditor; 00101 00102 ImageOverlayEditor* _editor; 00103 };*/ 00104 00105 struct OverlayCallback : public osgEarth::Util::ImageOverlay::ImageOverlayCallback 00106 { 00107 OverlayCallback(ImageOverlayEditor *editor): 00108 _editor(editor) 00109 { 00110 } 00111 00112 virtual void onOverlayChanged() 00113 { 00114 _editor->updateDraggers(); 00115 } 00116 00117 ImageOverlayEditor* _editor; 00118 }; 00119 00120 /***************************************************************************/ 00121 00122 00123 00124 00125 ImageOverlayEditor::ImageOverlayEditor(ImageOverlay* overlay, const osg::EllipsoidModel* ellipsoid, osg::Node* terrain): 00126 _overlay(overlay), 00127 _ellipsoid(ellipsoid), 00128 _terrain(terrain) 00129 { 00130 _overlayCallback = new OverlayCallback(this); 00131 _overlay->addCallback( _overlayCallback.get() ); 00132 addDragger( ImageOverlay::CONTROLPOINT_CENTER ); 00133 addDragger( ImageOverlay::CONTROLPOINT_LOWER_LEFT ); 00134 addDragger( ImageOverlay::CONTROLPOINT_LOWER_RIGHT ); 00135 addDragger( ImageOverlay::CONTROLPOINT_UPPER_LEFT ); 00136 addDragger( ImageOverlay::CONTROLPOINT_UPPER_RIGHT ); 00137 } 00138 00139 ImageOverlayEditor::~ImageOverlayEditor() 00140 { 00141 _overlay->removeCallback( _overlayCallback.get() ); 00142 } 00143 00144 void 00145 ImageOverlayEditor::addDragger( ImageOverlay::ControlPoint controlPoint ) 00146 { 00147 osg::Vec2d location = _overlay->getControlPoint( controlPoint ); 00148 osg::Matrixd matrix; 00149 _ellipsoid->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(location.y()), osg::DegreesToRadians(location.x()), 0, matrix); 00150 00151 IntersectingDragger* dragger = new IntersectingDragger; 00152 dragger->setNode( _terrain.get() ); 00153 dragger->setupDefaultGeometry(); 00154 dragger->setMatrix(matrix); 00155 dragger->setHandleEvents( true ); 00156 dragger->addDraggerCallback(new ImageOverlayDraggerCallback(_overlay.get(), _ellipsoid.get(), controlPoint)); 00157 00158 addChild(dragger); 00159 _draggers[ controlPoint ] = dragger; 00160 } 00161 00162 void 00163 ImageOverlayEditor::updateDraggers() 00164 { 00165 for (ImageOverlayEditor::ControlPointDraggerMap::iterator itr = getDraggers().begin(); itr != getDraggers().end(); ++itr) 00166 { 00167 //Get the location of the control point 00168 osg::Vec2d location = getOverlay()->getControlPoint( itr->first ); 00169 00170 osg::Matrixd matrix; 00171 00172 //Compute the geocentric location 00173 osg::ref_ptr< const osg::EllipsoidModel > ellipsoid = getEllipsoid(); 00174 osg::Vec3d geo_loc; 00175 ellipsoid->convertLatLongHeightToXYZ(osg::DegreesToRadians(location.y()), osg::DegreesToRadians(location.x()), 0, geo_loc.x(), geo_loc.y(), geo_loc.z()); 00176 00177 osg::Vec3d up = geo_loc; 00178 up.normalize(); 00179 00180 double segOffset = 50000; 00181 00182 osg::Vec3d start = geo_loc + (up * segOffset); 00183 osg::Vec3d end = geo_loc - (up * segOffset); 00184 00185 osgUtil::LineSegmentIntersector* i = new osgUtil::LineSegmentIntersector( start, end ); 00186 00187 osgUtil::IntersectionVisitor iv; 00188 iv.setIntersector( i ); 00189 getTerrain()->accept( iv ); 00190 00191 osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections(); 00192 if ( !results.empty() ) 00193 { 00194 const osgUtil::LineSegmentIntersector::Intersection& result = *results.begin(); 00195 geo_loc = result.getWorldIntersectPoint(); 00196 } 00197 00198 00199 getEllipsoid()->computeLocalToWorldTransformFromXYZ(geo_loc.x(), geo_loc.y(), geo_loc.z(), matrix); 00200 00201 00202 itr->second.get()->setMatrix( matrix ); 00203 00204 } 00205 }