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 <osgEarthAnnotation/CircleNode>
24 #include <osgEarthAnnotation/AnnotationRegistry>
25 #include <osgEarthAnnotation/AnnotationUtils>
26 #include <osgEarthFeatures/GeometryCompiler>
27 #include <osgEarthSymbology/GeometryFactory>
28 #include <osgEarthSymbology/ExtrusionSymbol>
29 #include <osgEarth/MapNode>
30 #include <osgEarth/DrapeableNode>
31 #include <osg/MatrixTransform>
32 #include <cmath>
33 
34 using namespace osgEarth;
35 using namespace osgEarth::Annotation;
36 using namespace osgEarth::Features;
37 using namespace osgEarth::Symbology;
38 
39 
CircleNode()40 CircleNode::CircleNode() :
41 LocalGeometryNode()
42 {
43     construct();
44 }
45 
46 void
set(const GeoPoint & position,const Distance & radius,const Style & style,const Angle & arcStart,const Angle & arcEnd,const bool pie)47 CircleNode::set(const GeoPoint&    position,
48                 const Distance&    radius,
49                 const Style&       style,
50                 const Angle&       arcStart,
51                 const Angle&       arcEnd,
52                 const bool         pie)
53 {
54     _radius = radius;
55     _arcStart = arcStart;
56     _arcEnd = arcEnd;
57     _pie = pie;
58     _style = style;
59 
60     setPosition(position);
61 
62     buildGeometry();
63 }
64 
65 void
construct()66 CircleNode::construct()
67 {
68     setName("Circle");
69 
70     _radius.set(1.0, Units::KILOMETERS);
71     _arcStart.set(0.0, Units::RADIANS);
72     _arcEnd.set(2.0*osg::PI, Units::RADIANS);
73     _pie = false;
74     _numSegments = 0;
75 }
76 
77 const Linear&
getRadius() const78 CircleNode::getRadius() const
79 {
80     return _radius;
81 }
82 
83 void
setRadius(const Linear & radius)84 CircleNode::setRadius( const Linear& radius )
85 {
86     if (_radius != radius )
87     {
88         _radius = radius;
89         buildGeometry();
90     }
91 }
92 
93 unsigned int
getNumSegments() const94 CircleNode::getNumSegments() const
95 {
96     return _numSegments;
97 }
98 
99 void
setNumSegments(unsigned int numSegments)100 CircleNode::setNumSegments(unsigned int numSegments )
101 {
102     if (_numSegments != numSegments )
103     {
104         _numSegments = numSegments;
105         buildGeometry();
106     }
107 }
108 
109 const Angle&
getArcStart(void) const110 CircleNode::getArcStart(void) const
111 {
112 	return (_arcStart);
113 }
114 
115 void
setArcStart(const Angle & arcStart)116 CircleNode::setArcStart(const Angle& arcStart)
117 {
118 	_arcStart = arcStart;
119 	buildGeometry();
120 }
121 
122 const Angle&
getArcEnd(void) const123 CircleNode::getArcEnd(void) const
124 {
125 	return (_arcEnd);
126 }
127 
128 void
setArcEnd(const Angle & arcEnd)129 CircleNode::setArcEnd(const Angle& arcEnd)
130 {
131 	_arcEnd = arcEnd;
132 	buildGeometry();
133 }
134 
135 const bool&
getPie(void) const136 CircleNode::getPie(void) const
137 {
138 	return (_pie);
139 }
140 
141 void
setPie(const bool & pie)142 CircleNode::setPie(const bool& pie)
143 {
144     _pie = pie;
145     buildGeometry();
146 }
147 
148 void
buildGeometry()149 CircleNode::buildGeometry()
150 {
151     // construct a local-origin circle.
152     GeometryFactory factory;
153     osg::ref_ptr<Geometry> geom;
154     if (std::abs(_arcEnd.as(Units::DEGREES) - _arcStart.as(Units::DEGREES)) >= 360.0)
155     {
156         geom = factory.createCircle(osg::Vec3d(0,0,0), _radius, _numSegments);
157     }
158     else
159     {
160         geom = factory.createArc(osg::Vec3d(0,0,0), _radius, _arcStart, _arcEnd, _numSegments, 0L, _pie);
161     }
162 
163     if ( geom.valid() )
164     {
165         setGeometry(geom.get());
166     }
167 }
168 
169 
170 //-------------------------------------------------------------------
171 
172 OSGEARTH_REGISTER_ANNOTATION( circle, osgEarth::Annotation::CircleNode );
173 
174 
CircleNode(const Config & conf,const osgDB::Options * dbOptions)175 CircleNode::CircleNode(const Config&         conf,
176                        const osgDB::Options* dbOptions) :
177 LocalGeometryNode(conf, dbOptions)
178 {
179     construct();
180 
181     conf.get( "radius",       _radius );
182     conf.get( "num_segments", _numSegments );
183 
184     buildGeometry();
185 }
186 
187 Config
getConfig() const188 CircleNode::getConfig() const
189 {
190     Config conf = LocalGeometryNode::getConfig();
191     conf.key() = "circle";
192 
193     conf.set( "radius", _radius );
194 
195     if ( _numSegments != 0 )
196         conf.add( "num_segments", _numSegments );
197 
198     return conf;
199 }
200