1 /* -*-c++-*- */
2 /* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2019 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
17 * IN THE SOFTWARE.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21 */
22 
23 #include <osg/Notify>
24 #include <osgGA/StateSetManipulator>
25 #include <osgGA/GUIEventHandler>
26 #include <osgViewer/Viewer>
27 #include <osgViewer/ViewerEventHandlers>
28 #include <osgEarth/MapNode>
29 #include <osgEarth/XmlUtils>
30 #include <osgEarth/Registry>
31 #include <osgEarth/Viewpoint>
32 #include <osgEarth/CullingUtils>
33 #include <osgEarth/GLUtils>
34 #include <osgEarthUtil/EarthManipulator>
35 #include <osgEarthUtil/AutoClipPlaneHandler>
36 #include <osgEarthUtil/Controls>
37 #include <osgEarthUtil/MouseCoordsTool>
38 #include <osgEarthUtil/ExampleResources>
39 #include <osgEarthSymbology/Color>
40 
41 #include <osgEarthUtil/MeasureTool>
42 
43 using namespace osgEarth::Util;
44 using namespace osgEarth::Util::Controls;
45 using namespace osgEarth::Symbology;
46 
47 class MyMeasureToolCallback : public MeasureToolHandler::MeasureToolEventHandler
48 {
49 public:
MyMeasureToolCallback(LabelControl * label)50     MyMeasureToolCallback(LabelControl* label):
51       _label(label)
52     {
53     }
54 
onDistanceChanged(MeasureToolHandler * sender,double distance)55     virtual void onDistanceChanged(MeasureToolHandler* sender, double distance)
56     {
57         std::stringstream ss;
58         ss << "Distance = " << std::setprecision(10) << distance << "m" << std::endl;
59         std::string str;
60         str = ss.str();
61         _label->setText( str );
62     }
63     LabelControl* _label;
64 };
65 
66 struct TogglePathHandler : public ControlEventHandler
67 {
TogglePathHandlerTogglePathHandler68     TogglePathHandler( MeasureToolHandler* tool) :
69     _tool( tool )
70     { }
71 
onValueChangedTogglePathHandler72     virtual void onValueChanged(Control* control, bool value) {
73         _tool->setIsPath( value );
74     }
75 
76     osg::ref_ptr<MeasureToolHandler> _tool;
77 };
78 
79 struct ToggleModeHandler : public ControlEventHandler
80 {
ToggleModeHandlerToggleModeHandler81     ToggleModeHandler( MeasureToolHandler* tool) :
82     _tool( tool )
83     { }
84 
onValueChangedToggleModeHandler85     virtual void onValueChanged(Control* control, bool value)
86     {
87         if (_tool->getGeoInterpolation() == GEOINTERP_GREAT_CIRCLE)
88         {
89             _tool->setGeoInterpolation( GEOINTERP_RHUMB_LINE);
90         }
91         else
92         {
93             _tool->setGeoInterpolation( GEOINTERP_GREAT_CIRCLE);
94         }
95     }
96 
97     osg::ref_ptr<MeasureToolHandler> _tool;
98 };
99 
100 
101 
102 int
main(int argc,char ** argv)103 main(int argc, char** argv)
104 {
105     osg::ArgumentParser arguments(&argc,argv);
106     osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );
107 
108     osgViewer::Viewer viewer(arguments);
109 
110     // load the .earth file from the command line.
111     osg::Node* earthNode = MapNodeHelper().load( arguments, &viewer );
112     if (!earthNode)
113     {
114         OE_NOTICE << "Unable to load earth model." << std::endl;
115         return 1;
116     }
117 
118     MapNode* mapNode = MapNode::findMapNode( earthNode );
119     if ( !mapNode )
120     {
121         OE_NOTICE << "Input file was not a .earth file" << std::endl;
122         return 1;
123     }
124 
125     earthNode->setNodeMask( 0x1 );
126 
127     osgEarth::Util::EarthManipulator* earthManip = new EarthManipulator();
128     viewer.setCameraManipulator( earthManip );
129 
130     osg::Group* root = new osg::Group();
131     root->addChild( earthNode );
132 
133     //Create the MeasureToolHandler
134     MeasureToolHandler* measureTool = new MeasureToolHandler(mapNode);
135     measureTool->setIntersectionMask( 0x1 );
136     viewer.addEventHandler( measureTool );
137 
138     //Create some controls to interact with the measuretool
139     ControlCanvas* canvas = new ControlCanvas();
140     root->addChild( canvas );
141     canvas->setNodeMask( 0x1 << 1 );
142 
143     Grid* grid = new Grid();
144     grid->setBackColor(0,0,0,0.5);
145     grid->setMargin( 10 );
146     grid->setPadding( 10 );
147     grid->setChildSpacing( 10 );
148     grid->setChildVertAlign( Control::ALIGN_CENTER );
149     grid->setAbsorbEvents( true );
150     grid->setVertAlign( Control::ALIGN_TOP );
151 
152     canvas->addControl( grid );
153 
154     //Add a label to display the distance
155     // Add a text label:
156     grid->setControl( 0, 0, new LabelControl("Distance:") );
157     LabelControl* label = new LabelControl();
158     label->setFont( osgEarth::Registry::instance()->getDefaultFont() );
159     label->setFontSize( 24.0f );
160     label->setHorizAlign( Control::ALIGN_LEFT );
161     label->setText("click to measure");
162     grid->setControl( 1, 0, label );
163 
164     //Add a callback to update the label when the distance changes
165     measureTool->addEventHandler( new MyMeasureToolCallback(label) );
166 
167     Style style = measureTool->getLineStyle();
168     style.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
169     style.getOrCreate<LineSymbol>()->stroke()->width() = 4.0f;
170     measureTool->setLineStyle(style);
171 
172     //Add a checkbox to control if we are doing path based measurement or just point to point
173     grid->setControl( 0, 1, new LabelControl("Path"));
174     CheckBoxControl* checkBox = new CheckBoxControl(false);
175     checkBox->setHorizAlign(Control::ALIGN_LEFT);
176     checkBox->addEventHandler( new TogglePathHandler(measureTool));
177     grid->setControl( 1, 1, checkBox);
178 
179     //Add a toggle to set the mode of the measuring tool
180     grid->setControl( 0, 2, new LabelControl("Great Circle"));
181     CheckBoxControl* mode = new CheckBoxControl(true);
182     mode->setHorizAlign(Control::ALIGN_LEFT);
183     mode->addEventHandler( new ToggleModeHandler(measureTool));
184     grid->setControl( 1, 2, mode);
185 
186     //Add a mouse coords readout:
187     LabelControl* mouseLabel = new LabelControl();
188     grid->setControl( 0, 3, new LabelControl("Mouse:"));
189     grid->setControl( 1, 3, mouseLabel );
190     viewer.addEventHandler(new MouseCoordsTool(mapNode, mouseLabel) );
191 
192     viewer.setSceneData( root );
193 
194     // add some stock OSG handlers:
195     viewer.addEventHandler(new osgViewer::StatsHandler());
196     viewer.addEventHandler(new osgViewer::WindowSizeHandler());
197     viewer.addEventHandler(new osgViewer::ThreadingHandler());
198     viewer.addEventHandler(new osgViewer::LODScaleHandler());
199     viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
200     viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
201 
202     return viewer.run();
203 }
204