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