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