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  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>
18  */
19 #include <osgEarth/Viewpoint>
20 
21 using namespace osgEarth;
22 
23 
24 Viewpoint::Viewpoint() :
25 _heading( Angle(       0.0, Units::DEGREES) ),
26 _pitch  ( Angle(     -30.0, Units::DEGREES) ),
27 _range  ( Distance(10000.0, Units::METERS)  )
28 {
IndexPair(int i, int j)29     //NOP
30 }
31 
32 Viewpoint::Viewpoint( const Viewpoint& rhs ) :
33 _name     ( rhs._name ),
34 _point    ( rhs._point ),
35 _heading  ( rhs._heading ),
36 _pitch    ( rhs._pitch ),
37 _range    ( rhs._range ),
38 _posOffset( rhs._posOffset),
39 _node     ( rhs._node.get() )
40 {
41     //NOP
42 }
43 
44 Viewpoint::Viewpoint(const char* name, double lon, double lat, double z, double h, double p, double range)
45 {
setJ(int j)46     if (name) _name = name;
47     _point->set( SpatialReference::get("wgs84"), lon, lat, z, ALTMODE_ABSOLUTE );
48     _heading->set( h, Units::DEGREES );
49     _pitch->set( p, Units::DEGREES );
equals(IndexPair pair)50     _range->set( range, Units::METERS );
51 }
52 
53 Viewpoint::Viewpoint(const Config& conf)
equals(Object o)54 {
55     conf.get( "name",    _name );
56     conf.get( "heading", _heading );
57     conf.get( "pitch",   _pitch );
58     conf.get( "range",   _range );
59 
60     // piecewise point.
61     std::string horiz = conf.value("srs");
62     if ( horiz.empty() )
63         horiz = "wgs84";
64 
65     const std::string vert = conf.value("vdatum");
66 
67     // try to parse an SRS, defaulting to WGS84 if not able to do so
68     osg::ref_ptr<const SpatialReference> srs = SpatialReference::create(horiz, vert);
69 
70     // try x/y/z variant:
71     if ( conf.hasValue("x") )
72     {
73         _point = GeoPoint(
74             srs.get(),
75             conf.value<double>("x", 0.0),
76             conf.value<double>("y", 0.0),
77             conf.value<double>("z", 0.0),
78             ALTMODE_ABSOLUTE );
79     }
80     else if ( conf.hasValue("lat") )
81     {
82         _point = GeoPoint(
83             srs.get(),
84             conf.value<double>("long",   0.0),
85             conf.value<double>("lat",    0.0),
86             conf.value<double>("height", 0.0),
87             ALTMODE_ABSOLUTE );
88     }
89 
90     double xOffset = conf.value("x_offset", 0.0);
91     double yOffset = conf.value("y_offset", 0.0);
92     double zOffset = conf.value("z_offset", 0.0);
93     if ( xOffset != 0.0 || yOffset != 0.0 || zOffset != 0.0 )
94     {
95         _posOffset->set(xOffset, yOffset, zOffset);
96     }
97 }
98 
99 osg::ref_ptr<osg::Node>
100 Viewpoint::getNode() const
101 {
102     osg::ref_ptr<osg::Node> node;
103     _node.lock(node);
104     return node;
105 }
106 
107 #define CONF_STR Stringify() << std::fixed << std::setprecision(4)
108 
109 Config
110 Viewpoint::getConfig() const
111 {
112     Config conf( "viewpoint" );
113 
114     conf.set( "name",    _name );
115     conf.set( "heading", _heading );
116     conf.set( "pitch",   _pitch );
117     conf.set( "range",   _range );
118 
119     if ( _point.isSet() )
120     {
121         if ( _point->getSRS()->isGeographic() )
122         {
123             conf.set("long",   _point->x());
124             conf.set("lat",    _point->y());
125             conf.set("height", _point->z());
126         }
127         else
128         {
129             conf.set("x", _point->x());
130             conf.set("y", _point->y());
131             conf.set("z", _point->z());
132         }
133 
134         conf.set("srs", _point->getSRS()->getHorizInitString());
135 
136         if ( _point->getSRS()->getVerticalDatum() )
137             conf.set("vdatum", _point->getSRS()->getVertInitString());
138     }
139 
140     if ( _posOffset.isSet() )
141     {
142         conf.set("x_offset", _posOffset->x());
143         conf.set("y_offset", _posOffset->y());
144         conf.set("z_offset", _posOffset->z());
145     }
146 
147     return conf;
148 }
149 
150 bool
151 Viewpoint::isValid() const
152 {
153     return
154         (_point.isSet() && _point->isValid()) ||
155         (_node.valid());
156 }
157 
158 std::string
159 Viewpoint::toString() const
160 {
161     if ( _point.isSet() )
162     {
163         return Stringify()
164             << "x="   << _point->x()
165             << ", y=" << _point->y()
166             << ", z=" << _point->z()
167             << ", h=" << _heading->to(Units::DEGREES).asParseableString()
168             << ", p=" << _pitch->to(Units::DEGREES).asParseableString()
169             << ", d=" << _range->asParseableString()
170             << ", xo=" << _posOffset->x()
171             << ", yo=" << _posOffset->y()
172             << ", zo=" << _posOffset->z();
173     }
174     else
175     {
176         return Stringify()
177             << "attached to node; "
178             << ", h=" << _heading->to(Units::DEGREES).asParseableString()
179             << ", p=" << _pitch->to(Units::DEGREES).asParseableString()
180             << ", d=" << _range->asParseableString()
181             << ", xo=" << _posOffset->x()
182             << ", yo=" << _posOffset->y()
183             << ", zo=" << _posOffset->z();
184     }
185 }
186