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 #include <osgEarthAnnotation/EllipseNode>
23 #include <osgEarthAnnotation/AnnotationRegistry>
24 #include <osgEarthAnnotation/AnnotationUtils>
25 #include <osgEarthFeatures/GeometryCompiler>
26 #include <osgEarthSymbology/GeometryFactory>
27 #include <osgEarth/DrapeableNode>
28 #include <osgEarth/MapNode>
29 #include <cmath>
30 
31 using namespace osgEarth;
32 using namespace osgEarth::Annotation;
33 using namespace osgEarth::Features;
34 using namespace osgEarth::Symbology;
35 
36 
EllipseNode()37 EllipseNode::EllipseNode() :
38 LocalGeometryNode()
39 {
40     construct();
41 }
42 
43 void
construct()44 EllipseNode::construct()
45 {
46     _radiusMajor.set(1.0, Units::KILOMETERS);
47     _radiusMinor.set(0.5, Units::KILOMETERS);
48     _rotationAngle = 0.0;
49     _arcStart.set(0.0, Units::RADIANS);
50     _arcEnd.set(2.0*osg::PI, Units::RADIANS);
51     _pie = false;
52     _numSegments = 0;
53 }
54 
55 void
set(const GeoPoint & position,const Distance & radiusMajor,const Distance & radiusMinor,const Angle & rotationAngle,const Style & style,const Angle & arcStart,const Angle & arcEnd,const bool pie)56 EllipseNode::set(const GeoPoint& position,
57                  const Distance& radiusMajor,
58                  const Distance& radiusMinor,
59                  const Angle&    rotationAngle,
60                  const Style&    style,
61                  const Angle&    arcStart,
62                  const Angle&    arcEnd,
63                  const bool      pie)
64 {
65     _radiusMajor = radiusMajor;
66     _radiusMinor = radiusMinor;
67     _rotationAngle = rotationAngle;
68     _arcStart = arcStart;
69     _arcEnd = arcEnd;
70     _pie = pie;
71 
72     _style = style;
73 
74     setPosition(position);
75 
76     buildGeometry();
77 }
78 
79 unsigned int
getNumSegments() const80 EllipseNode::getNumSegments() const
81 {
82     return _numSegments;
83 }
84 
85 void
setNumSegments(unsigned numSegments)86 EllipseNode::setNumSegments(unsigned numSegments)
87 {
88     if (_numSegments != numSegments )
89     {
90         _numSegments = numSegments;
91         buildGeometry();
92     }
93 }
94 
95 
96 const Linear&
getRadiusMajor() const97 EllipseNode::getRadiusMajor() const
98 {
99     return _radiusMajor;
100 }
101 
102 const Linear&
getRadiusMinor() const103 EllipseNode::getRadiusMinor() const
104 {
105     return _radiusMinor;
106 }
107 
108 void
setRadiusMajor(const Linear & radiusMajor)109 EllipseNode::setRadiusMajor( const Linear& radiusMajor )
110 {
111     setRadii( radiusMajor, _radiusMinor );
112 }
113 
114 
115 void
setRadiusMinor(const Linear & radiusMinor)116 EllipseNode::setRadiusMinor( const Linear& radiusMinor )
117 {
118     setRadii( _radiusMajor, radiusMinor );
119 }
120 
121 void
setRadii(const Linear & radiusMajor,const Linear & radiusMinor)122 EllipseNode::setRadii( const Linear& radiusMajor, const Linear& radiusMinor )
123 {
124     if (_radiusMajor != radiusMajor || _radiusMinor != radiusMinor )
125     {
126         _radiusMajor = radiusMajor;
127         _radiusMinor = radiusMinor;
128         buildGeometry();
129     }
130 }
131 
132 const Angular&
getRotationAngle() const133 EllipseNode::getRotationAngle() const
134 {
135     return _rotationAngle;
136 }
137 
138 void
setRotationAngle(const Angular & rotationAngle)139 EllipseNode::setRotationAngle(const Angular& rotationAngle)
140 {
141     if (_rotationAngle != rotationAngle)
142     {
143         _rotationAngle = rotationAngle;
144         buildGeometry();
145     }
146 }
147 const Angle&
getArcStart(void) const148 EllipseNode::getArcStart(void) const
149 {
150     return _arcStart;
151 }
152 
153 void
setArcStart(const Angle & arcStart)154 EllipseNode::setArcStart(const Angle& arcStart)
155 {
156     _arcStart = arcStart;
157     buildGeometry();
158 }
159 
160 const Angle&
getArcEnd(void) const161 EllipseNode::getArcEnd(void) const
162 {
163     return _arcEnd;
164 }
165 
166 void
setArcEnd(const Angle & arcEnd)167 EllipseNode::setArcEnd(const Angle& arcEnd)
168 {
169     _arcEnd = arcEnd;
170     buildGeometry();
171 }
172 
173 const bool&
getPie(void) const174 EllipseNode::getPie(void) const
175 {
176 	return _pie;
177 }
178 
179 void
setPie(const bool & pie)180 EllipseNode::setPie(const bool& pie)
181 {
182 	_pie = pie;
183 	buildGeometry();
184 }
185 
186 void
buildGeometry()187 EllipseNode::buildGeometry()
188 {
189     // construct a local-origin ellipse.
190     GeometryFactory factory;
191 
192     osg::ref_ptr<Geometry> geom;
193 
194     if (std::abs(_arcEnd.as(Units::DEGREES) - _arcStart.as(Units::DEGREES)) >= 360.0)
195     {
196         geom = factory.createEllipse(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _numSegments);
197     }
198     else
199     {
200         geom = factory.createEllipticalArc(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _arcStart, _arcEnd, _numSegments, 0L, _pie);
201     }
202 
203     if ( geom.valid() )
204     {
205         setGeometry( geom.get() );
206     }
207 }
208 
209 
210 
211 //-------------------------------------------------------------------
212 
213 OSGEARTH_REGISTER_ANNOTATION( ellipse, osgEarth::Annotation::EllipseNode );
214 
215 
EllipseNode(const Config & conf,const osgDB::Options * dbOptions)216 EllipseNode::EllipseNode(const Config&         conf,
217                          const osgDB::Options* dbOptions) :
218 LocalGeometryNode(conf, dbOptions)
219 {
220     construct();
221 
222     conf.get( "radius_major", _radiusMajor );
223     conf.get( "radius_minor", _radiusMinor );
224     conf.get( "rotation", _rotationAngle );
225     conf.get( "num_segments", _numSegments );
226 
227     buildGeometry();
228 }
229 
230 Config
getConfig() const231 EllipseNode::getConfig() const
232 {
233     Config conf = LocalGeometryNode::getConfig();
234     conf.key() = "ellipse";
235 
236     conf.set( "radius_major", _radiusMajor );
237     conf.set( "radius_minor", _radiusMinor );
238     conf.set( "rotation", _rotationAngle );
239 
240     if ( _numSegments != 0 )
241         conf.set( "num_segments", _numSegments );
242 
243     return conf;
244 }
245