GPX-Visualizer/Track.cpp
2021-06-22 16:40:39 -04:00

177 lines
4.2 KiB
C++

#include "Track.h"
#include "Xml.h"
#include <GL/glut.h>
#include <syslog.h>
#include <iostream>
#include <iomanip>
#include <fstream>
bool ParseFile(std::vector<Track> &out_tracks,
const std::string &file_and_path)
{
std::ifstream ifs(file_and_path);
if(!ifs.is_open())
{
std::cerr << "Couldn't open " << file_and_path << "." << std::endl;
return false;
}
// get size
ifs.seekg(0, std::ios_base::end);
auto end = ifs.tellg();
std::string file_str(end, '\0');
ifs.seekg(0, std::ios_base::beg); // back to beginning to read
ifs.read(&file_str[0], end);
// parse it (warning: possibly destructive / not const)
using namespace rapidxml;
xml_document<> doc; // character type defaults to char
doc.parse<0>(&file_str[0]); // 0 means default parse flags
xml_node<> *seg_node = recursive_find_next_node(doc.first_node(), "trkseg");
if(!seg_node)
{
std::cerr << "Couldn't find any <trkseg> nodes for file \""
<< file_and_path
<< "\"." << std::endl;
return false;
}
Track t;
for(int seg_count = 0;
seg_node;
++seg_count, seg_node = recursive_find_next_node(seg_node->next_sibling(), "trkseg"))
{
xml_node<> *node = recursive_find_next_node(seg_node, "trkpt");
if(!node)
{
std::cerr << "Couldn't find a <trkpt> node for file \""
<< file_and_path
<< "\" <trkseg> #" << seg_count << "." << std::endl;
return false;
}
// recursively search for all trkpt nodes:
for(; node; node = recursive_find_next_node(node->next_sibling(), "trkpt"))
{
bool found_lat = false;
bool found_lon = false;
bool found_ele = false;
Point p;
for(xml_attribute<> *attr = node->first_attribute();
attr;
attr = attr->next_attribute())
{
if(std::string(attr->name()) == "lat")
{
try {
p.lat = std::atof(attr->value());
found_lat = true;
} catch(const std::exception &e) {
syslog(LOG_USER|LOG_DEBUG,"%s:%d:%s Error Parsing lat",
__FILE__,__LINE__,__PRETTY_FUNCTION__);
}
}
if(std::string(attr->name()) == "lon")
{
try {
p.lon = std::atof(attr->value());
found_lon = true;
} catch(const std::exception &e) {
syslog(LOG_USER|LOG_DEBUG,"%s:%d:%s Error Parsing lon",
__FILE__,__LINE__,__PRETTY_FUNCTION__);
}
}
}
auto ele_node = node->first_node("ele");
if(ele_node)
{
try {
p.ele = std::atof(ele_node->value());
found_ele = true;
} catch(const std::exception &e) {
syslog(LOG_USER|LOG_DEBUG,"%s:%d:%s Error Parsing ele",
__FILE__,__LINE__,__PRETTY_FUNCTION__);
}
}
if(found_lat && found_lon && found_ele)
t.points.push_back(p);
else if(found_lat || found_lon || found_ele)
syslog(LOG_USER|LOG_DEBUG, "%s:%d:%s Incomplete trkpt",
__FILE__,__LINE__,__PRETTY_FUNCTION__);
}
}
// Bring track to a scale that we're comfortable rendering:
// Grab stats:
bool first = true;
for(auto &p : t.points)
{
if(first)
{
first = false;
t.min.lat = t.max.lat = p.lat;
t.min.lon = t.max.lon = p.lon;
t.min.ele = t.max.ele = p.ele;
}
else
{
if(p.lat < t.min.lat)
t.min.lat = p.lat;
else if(p.lat > t.max.lat)
t.max.lat = p.lat;
if(p.lon < t.min.lon)
t.min.lon = p.lon;
else if(p.lon > t.max.lon)
t.max.lon = p.lon;
if(p.ele < t.min.ele)
t.min.ele = p.ele;
else if(p.ele > t.max.ele)
t.max.ele = p.ele;
}
// NOTE(dev): This must be done AFTER the translation so it doesn't get skewered
// p.lat *= 500;
// p.lon *= 500;
// p.ele *= 0.04;
}
out_tracks.push_back(t);
ifs.close();
std::cout << std::setw(6) << t.points.size() << " tracks points "
<< "found in \"" << file_and_path << "\"." << std::endl;
return true;
}
void draw(const Track &track)
{
// glLineWidth(1.0f);
// Draw bike path
glBegin(GL_LINE_STRIP);
for(auto p : track.points)
{
// auto val = (50 + (p.ele * 10)) / 180.0;
// val /= 2.0;
// double val = (p.ele - track.min.ele) / (track.max.ele - track.min.ele);
// val /= 2.0 + 0.5;
// val *= 255;
// glColor3d(val, val, val);
glColor3d(200, 200, 200);
glVertex3f(p.lat,
p.ele,
p.lon);
}
glEnd();
glutPostRedisplay();
}