root/OpenSceneGraph/trunk/examples/osggpx/osggpx.cpp @ 10949

Revision 10949, 13.9 kB (checked in by robert, 4 years ago)

Added missing .get()'s

Line 
1/* OpenSceneGraph example, osggpx.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/Node>
20#include <osg/Geometry>
21#include <osg/Notify>
22#include <osg/MatrixTransform>
23#include <osg/Texture2D>
24#include <osg/DrawPixels>
25#include <osg/PolygonOffset>
26#include <osg/Geode>
27#include <osg/CoordinateSystemNode>
28
29#include <osgDB/Registry>
30#include <osgDB/ReadFile>
31#include <osgDB/FileUtils>
32#include <osgDB/FileNameUtils>
33#include <osgDB/XmlParser>
34
35#include <osgText/Text>
36
37#include <osgGA/TerrainManipulator>
38#include <osgViewer/Viewer>
39
40class TrackSegment : public osg::Object
41{
42public:
43    TrackSegment() {}
44
45    TrackSegment(const TrackSegment& ts, const osg::CopyOp=osg::CopyOp::SHALLOW_COPY) {}
46
47    META_Object(osg, TrackSegment)
48
49    struct TrackPoint
50    {
51        TrackPoint():
52            latitude(0.0),
53            longitude(0.0),
54            elevation(0.0),
55            time(0.0) {}
56
57        double latitude;
58        double longitude;
59        double elevation;
60        double time;
61    };
62
63    typedef std::vector< TrackPoint > TrackPoints;
64
65    void addTrackPoint(const TrackPoint& trackPoint) { _trackPoints.push_back(trackPoint); }
66
67    TrackPoints& getTrackPoints() { return _trackPoints; }
68    const TrackPoints& getTrackPoints() const { return _trackPoints; }
69
70protected:
71    virtual ~TrackSegment() {}
72
73    TrackPoints _trackPoints;
74};
75
76class Track : public osg::Object
77{
78public:
79    Track() {}
80
81    Track(const Track& track, const osg::CopyOp=osg::CopyOp::SHALLOW_COPY) {}
82
83    META_Object(osg, Track)
84
85    typedef std::vector< osg::ref_ptr<TrackSegment> > TrackSegments;
86
87    void addTrackSegment(TrackSegment* trackSegment) { _trackSegments.push_back(trackSegment); }
88
89    TrackSegments& getTrackSegments() { return _trackSegments; }
90    const TrackSegments& getTrackSegments() const { return _trackSegments; }
91
92protected:
93
94    virtual ~Track() {}
95
96    TrackSegments _trackSegments;
97};
98
99double convertTime(const std::string& timestr)
100{
101    //osg::notify(osg::NOTICE)<<"       time = "<<timestr<<std::endl;
102    return 0;
103}
104
105Track* readTrack(const std::string& filename)
106{
107    std::string foundFilename = osgDB::findDataFile(filename);
108    if (foundFilename.empty()) return 0;
109
110    std::string ext = osgDB::getFileExtension(foundFilename);
111    if (ext!="gpx") return 0;
112
113    osgDB::XmlNode::Input input;
114    input.open(foundFilename);
115    input.readAllDataIntoBuffer();
116
117    osg::ref_ptr<osgDB::XmlNode> doc = new osgDB::XmlNode;
118    doc->read(input);
119
120    osgDB::XmlNode* root = 0;
121    for(osgDB::XmlNode::Children::iterator itr = doc->children.begin();
122        itr != doc->children.end() && !root;
123        ++itr)
124    {
125        if ((*itr)->name=="gpx") root = itr->get();
126    }
127
128    if (!root) return 0;
129
130    std::string latitude("lat");
131    std::string longitude("lon");
132
133    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
134        itr != root->children.end();
135        ++itr)
136    {
137        if ((*itr)->name=="trk")
138        {
139            osg::ref_ptr<Track> track = new Track;
140            track->setName(filename);
141
142            for(osgDB::XmlNode::Children::iterator citr = (*itr)->children.begin();
143                citr != (*itr)->children.end();
144                ++citr)
145            {
146                if ((*citr)->name=="trkseg")
147                {
148                    osg::ref_ptr<TrackSegment> trackSegment = new TrackSegment;
149                    for(osgDB::XmlNode::Children::iterator sitr = (*citr)->children.begin();
150                        sitr != (*citr)->children.end();
151                        ++sitr)
152                    {
153                        if ((*sitr)->name=="trkpt")
154                        {
155                            osgDB::XmlNode* trkpt = sitr->get();
156                            TrackSegment::TrackPoint point;
157                            bool valid = false;
158                            if (trkpt->properties.count(latitude)!=0)
159                            {
160                                valid = true;
161                                point.latitude = osg::asciiToDouble(trkpt->properties[latitude].c_str());
162                            }
163                            if (trkpt->properties.count(longitude)!=0)
164                            {
165                                valid = true;
166                                point.longitude = osg::asciiToDouble(trkpt->properties[longitude].c_str());
167                            }
168
169                            for(osgDB::XmlNode::Children::iterator pitr = trkpt->children.begin();
170                                pitr != trkpt->children.end();
171                                ++pitr)
172                            {
173                                if ((*pitr)->name=="ele") point.elevation = osg::asciiToDouble((*pitr)->contents.c_str());
174                                else if ((*pitr)->name=="time") point.time = convertTime((*pitr)->contents);
175                            }
176
177                            if (valid)
178                            {
179                                // osg::notify(osg::NOTICE)<<"  point.latitude="<<point.latitude<<", longitude="<<point.longitude<<", elev="<<point.elevation<<", time="<<point.time<<std::endl;
180                                trackSegment->addTrackPoint(point);
181                            }
182                        }
183                    }
184                    if (!trackSegment->getTrackPoints().empty())
185                    {
186                        track->addTrackSegment(trackSegment.get());
187                    }
188                }
189            }
190
191
192            return track.release();
193        }
194    }
195
196    return 0;
197}
198
199TrackSegment* computeSmoothedTrackSegment(TrackSegment* ts)
200{
201    if (!ts) return 0;
202
203    const TrackSegment::TrackPoints& orig_points = ts->getTrackPoints();
204
205    if (orig_points.size()>2)
206    {
207        // only do smoothing if we have more than two points.
208        osg::ref_ptr<TrackSegment> new_ts = new TrackSegment;
209
210        TrackSegment::TrackPoints& new_points = new_ts->getTrackPoints();
211        new_points.resize(orig_points.size());
212
213        new_points[0] = orig_points[0];
214        new_points[orig_points.size()-1] = orig_points[orig_points.size()-1];
215
216        for(unsigned int i=1; i<orig_points.size()-1; ++i)
217        {
218            new_points[i].latitude = (orig_points[i-1].latitude+orig_points[i].latitude+orig_points[i+1].latitude)/3.0;
219            new_points[i].longitude = (orig_points[i-1].longitude+orig_points[i].longitude+orig_points[i+1].longitude)/3.0;
220            new_points[i].elevation = (orig_points[i-1].elevation+orig_points[i].elevation+orig_points[i+1].elevation)/3.0;
221        }
222        return new_ts.release();
223    }
224    else
225    {
226        // we have two or less points and can't do smoothing, so will just return original TrackSegment
227        return ts;
228    }
229
230}
231
232Track* computeSmoothedTrack(Track* track)
233{
234    osg::ref_ptr<Track> new_track = new Track;
235
236    for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
237        itr != track->getTrackSegments().end();
238        ++itr)
239    {
240        new_track->addTrackSegment(computeSmoothedTrackSegment(itr->get()));
241    }
242
243    return new_track.release();
244}
245
246osg::Node* createTrackModel(Track* track, const osg::Vec4& colour)
247{
248    osg::ref_ptr<osg::EllipsoidModel> em = new osg::EllipsoidModel;
249
250    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
251
252    for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
253        itr != track->getTrackSegments().end();
254        ++itr)
255    {
256        const TrackSegment::TrackPoints& points = (*itr)->getTrackPoints();
257        if (points.size()<2) continue;
258
259        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
260        osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
261        geometry->setVertexArray(vertices.get());
262        vertices->resize(points.size());
263        for(unsigned int i=0; i<points.size(); ++i)
264        {
265            osg::Vec3d point;
266            em->convertLatLongHeightToXYZ(osg::DegreesToRadians(points[i].latitude), osg::DegreesToRadians(points[i].longitude), points[i].elevation,
267                                          point.x(), point.y(), point.z());
268
269           (*vertices)[i] = point;
270        }
271
272        osg::ref_ptr<osg::Vec4Array> colours = new osg::Vec4Array;
273        colours->push_back(colour);
274        geometry->setColorArray(colours.get());
275        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
276
277        geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, points.size()));
278
279        geode->addDrawable(geometry.get());
280    }
281
282    geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
283
284    return geode.release();
285}
286
287int main(int argv, char **argc)
288{
289    osg::ArgumentParser arguments(&argv, argc);
290
291    typedef std::list< osg::ref_ptr<Track> > Tracks;
292    Tracks tracks;
293
294    bool smooth = false;
295    while (arguments.read("-s") || arguments.read("--smooth")) smooth = true;
296
297    std::string trackFilename;
298    while (arguments.read("-t",trackFilename))
299    {
300        osg::ref_ptr<Track> track = readTrack(trackFilename);
301        if (track.valid()) tracks.push_back(track.get());
302    }
303
304    osg::ref_ptr<osg::EllipsoidModel> em = new osg::EllipsoidModel;
305
306    osg::ref_ptr<osg::Group> group = new osg::Group;
307
308    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
309    if (loadedModel.valid()) group->addChild(loadedModel.get());
310
311    for(Tracks::iterator itr = tracks.begin();
312        itr != tracks.end();
313        ++itr)
314    {
315        Track* track = itr->get();
316
317        group->addChild(createTrackModel(track, osg::Vec4(1.0,1.0,1.0,1.0)));
318
319        // smooth the track
320        if (smooth)
321        {
322            for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
323                itr != track->getTrackSegments().end();
324                ++itr)
325            {
326                *itr = computeSmoothedTrackSegment(itr->get());
327            }
328
329            for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
330                itr != track->getTrackSegments().end();
331                ++itr)
332            {
333                *itr = computeSmoothedTrackSegment(itr->get());
334            }
335
336            for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
337                itr != track->getTrackSegments().end();
338                ++itr)
339            {
340                *itr = computeSmoothedTrackSegment(itr->get());
341            }
342
343            for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
344                itr != track->getTrackSegments().end();
345                ++itr)
346            {
347                *itr = computeSmoothedTrackSegment(itr->get());
348            }
349        }
350
351        double totalDistance = 0.0;
352        double totalAscent = 0.0;
353        double totalDescent = 0.0;
354
355        osg::notify(osg::NOTICE)<<"Track read "<<track->getName()<<std::endl;
356        for(Track::TrackSegments::iterator itr = track->getTrackSegments().begin();
357            itr != track->getTrackSegments().end();
358            ++itr)
359        {
360            TrackSegment* ts = itr->get();
361
362            const TrackSegment::TrackPoints& points = ts->getTrackPoints();
363            if (points.size()>1)
364            {
365                TrackSegment::TrackPoints::iterator pitr = ts->getTrackPoints().begin();
366                osg::Vec3d previousPos;
367                double previousElevation = pitr->elevation;
368                em->convertLatLongHeightToXYZ(osg::DegreesToRadians(pitr->latitude), osg::DegreesToRadians(pitr->longitude), 0.0,
369                                              previousPos.x(), previousPos.y(), previousPos.z());
370                ++pitr;
371
372                for(;
373                    pitr != ts->getTrackPoints().end();
374                    ++pitr)
375                {
376                    osg::Vec3d newPos;
377                    double newElevation = pitr->elevation;
378                    em->convertLatLongHeightToXYZ(osg::DegreesToRadians(pitr->latitude), osg::DegreesToRadians(pitr->longitude), 0.0,
379                                                newPos.x(), newPos.y(), newPos.z());
380
381                    double distance = (newPos-previousPos).length();
382
383                    totalDistance += distance;
384                    if (newElevation>previousElevation) totalAscent += (newElevation-previousElevation);
385                    else totalDescent += (previousElevation-newElevation);
386
387                    osg::notify(osg::NOTICE)<<"     distance="<<distance<<", "<<newElevation-previousElevation<<std::endl;
388
389                    previousPos = newPos;
390                    previousElevation = newElevation;
391                }
392            }
393        }
394
395        double metersToFeet = 1 / 0.3048;
396        double metersToMiles = 1.0 / 1609.344;
397
398        osg::notify(osg::NOTICE)<<"totalDistance = "<<totalDistance<<"m, "<<totalDistance*metersToMiles<<" miles"<<std::endl;
399        osg::notify(osg::NOTICE)<<"totalAscent = "<<totalAscent<<"m, "<<totalAscent*metersToFeet<<"ft"<<std::endl;
400        osg::notify(osg::NOTICE)<<"totalDescent = "<<totalDescent<<"m, "<<totalDescent*metersToFeet<<"ft"<<std::endl;
401
402    }
403
404    osgViewer::Viewer viewer(arguments);
405    viewer.setCameraManipulator(new osgGA::TerrainManipulator);
406    viewer.setSceneData(group.get());
407    return viewer.run();
408
409}
Note: See TracBrowser for help on using the browser.