2021-03-20 22:56:03 -04:00
|
|
|
#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
|
|
|
|
|
2021-06-14 20:39:38 -04:00
|
|
|
xml_node<> *seg_node = recursive_find_next_node(doc.first_node(), "trkseg");
|
|
|
|
if(!seg_node)
|
2021-03-20 22:56:03 -04:00
|
|
|
{
|
2021-06-14 20:39:38 -04:00
|
|
|
std::cerr << "Couldn't find any <trkseg> nodes for file \""
|
|
|
|
<< file_and_path
|
|
|
|
<< "\"." << std::endl;
|
2021-03-20 22:56:03 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Track t;
|
|
|
|
|
2021-06-14 20:39:38 -04:00
|
|
|
for(int seg_count = 0;
|
|
|
|
seg_node;
|
|
|
|
++seg_count, seg_node = recursive_find_next_node(seg_node->next_sibling(), "trkseg"))
|
2021-03-20 22:56:03 -04:00
|
|
|
{
|
2021-06-14 20:39:38 -04:00
|
|
|
xml_node<> *node = recursive_find_next_node(seg_node, "trkpt");
|
|
|
|
if(!node)
|
2021-03-20 22:56:03 -04:00
|
|
|
{
|
2021-06-14 20:39:38 -04:00
|
|
|
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())
|
2021-03-20 22:56:03 -04:00
|
|
|
{
|
2021-06-14 20:39:38 -04:00
|
|
|
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__);
|
|
|
|
}
|
2021-03-20 22:56:03 -04:00
|
|
|
}
|
|
|
|
}
|
2021-06-14 20:39:38 -04:00
|
|
|
auto ele_node = node->first_node("ele");
|
|
|
|
if(ele_node)
|
2021-03-20 22:56:03 -04:00
|
|
|
{
|
|
|
|
try {
|
2021-06-14 20:39:38 -04:00
|
|
|
p.ele = std::atof(ele_node->value());
|
|
|
|
found_ele = true;
|
2021-03-20 22:56:03 -04:00
|
|
|
} catch(const std::exception &e) {
|
2021-06-14 20:39:38 -04:00
|
|
|
syslog(LOG_USER|LOG_DEBUG,"%s:%d:%s Error Parsing ele",
|
2021-03-20 22:56:03 -04:00
|
|
|
__FILE__,__LINE__,__PRETTY_FUNCTION__);
|
|
|
|
}
|
|
|
|
}
|
2021-06-14 20:39:38 -04:00
|
|
|
|
|
|
|
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",
|
2021-03-20 22:56:03 -04:00
|
|
|
__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;
|
|
|
|
}
|
2021-06-14 20:39:38 -04:00
|
|
|
// 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;
|
2021-03-20 22:56:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2021-06-14 20:39:38 -04:00
|
|
|
// 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);
|
2021-06-21 23:11:21 -04:00
|
|
|
glVertex3f(p.lat,// - track.min.lat,
|
|
|
|
p.ele,// - track.min.ele,
|
|
|
|
p.lon);// - track.min.lon);
|
|
|
|
static bool asdf = true;
|
2021-03-20 22:56:03 -04:00
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
// usleep(100000);
|
|
|
|
|
|
|
|
glutPostRedisplay();
|
|
|
|
}
|