Split up files. Added rapidxml for xml parsing.

This commit is contained in:
David Vereb 2021-03-20 22:56:03 -04:00
parent a5175799ba
commit 40d41361fc
7 changed files with 2888 additions and 104 deletions

View File

@ -1,2 +1,4 @@
a.out: main.cpp
clang++ -std=c++17 -g -o a.out main.cpp -lGL -lGLU -lglut -lstdc++fs
a.out: *.cpp
clang++ -std=c++17 -g -o a.out main.cpp \
camera/Camera.cpp Track.cpp Xml.cpp \
-lGL -lGLU -lglut -lstdc++fs

152
Track.cpp Normal file
View File

@ -0,0 +1,152 @@
#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<> *node = recursive_find_next_node(doc.first_node(), "trkpt");
if(!node)
{
std::cerr << "Couldn't find a <trkpt> node for file \"" << file_and_path << "\"." << std::endl;
return false;
}
Track t;
// 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;
}
p.lat *= 500;
p.lon *= 500;
p.ele *= 0.2;
}
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;
glColor3d(val / 2.0, val / 2.0, val / 2.0);
glVertex3f(p.lat, p.ele, p.lon);
}
glEnd();
// usleep(100000);
glutPostRedisplay();
}

27
Track.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef TRACK_H
#define TRACK_H
#include <vector>
#include <string>
struct Point {
float lat;
float lon;
float ele;
};
struct Track {
public:
std::vector<Point> points;
Point min;
Point max;
};
static std::vector<Track> tracks;
bool ParseFile(std::vector<Track> &out_tracks,
const std::string &file_and_path);
void draw(const Track &track);
#endif

26
Xml.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "Xml.h"
using namespace rapidxml;
xml_node<>* recursive_find_next_node(xml_node<> *node, const std::string &node_name)
{
if(!node)
return nullptr;
// go through each sibling node...
for(; node; node = node->next_sibling())
{
if(node->name() == node_name)
return node;
// first make sure none of the children nodes have this name, too.
if(node->first_node() != nullptr)
{
auto child_node = recursive_find_next_node(node->first_node(), node_name);
if(child_node)
return child_node;
}
}
return nullptr;
}

13
Xml.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef XML_H
#define XML_H
#include "rapidxml.hpp"
#include <string>
rapidxml::xml_node<>* recursive_find_next_node(
rapidxml::xml_node<> *node,
const std::string &node_name
);
#endif

172
main.cpp
View File

@ -1,11 +1,13 @@
#include "rapidxml.hpp"
#include "camera/Camera.h"
#include "Xml.h"
#include "Track.h"
#include <GL/glut.h>
#include <experimental/filesystem>
#include <syslog.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <math.h> // fmod
#include <unistd.h>
@ -14,119 +16,41 @@
GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
struct Point {
float lat;
float lon;
float ele;
};
static std::vector<std::vector<Point> > tracks;
bool ParseFile(std::vector<std::vector<Point>> &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 -2;
}
std::string line = "";
bool first = true;
float diff_lat, diff_lon, diff_ele;
std::vector<Point> track;
while(std::getline(ifs, line))
{
// get starting position of field NAME
auto lat = line.find("lat=\"");
if(lat == std::string::npos)
continue;
// get ending position of field DATA
auto lat_to = line.find("\"", lat);
if(lat_to == std::string::npos)
continue;
// get starting position of field NAME
auto lon = line.find("lon=\"", lat_to);
if(lon == std::string::npos)
continue;
// get ending position of field DATA
auto lon_to = line.find("\"", lon);
if(lon_to == std::string::npos)
continue;
auto ele = line.find("<ele>", lon_to);
if(ele == std::string::npos)
continue;
auto ele_to = line.find("</ele>", ele);
if(ele_to == std::string::npos)
continue;
Point p;
try {
p.lat = std::atof(line.substr(lat + 5, lat_to).c_str()) * 200;
p.lon = std::atof(line.substr(lon + 5, lon_to).c_str()) * 200;
p.ele = std::atof(line.substr(ele + 5, ele_to).c_str()) * 0.1;
} catch (const std::exception &e) {
std::cerr << "Error in file " << file_and_path
<< ", line \"" << line << "\"."
<< std::endl;
continue;
}
track.push_back(p);
}
out_tracks.push_back(track);
ifs.close();
}
Camera camera;
// TODO(dev):
// As per https://www.opengl.org/resources/libraries/glut/spec3/node11.html
// "Therefore, GLUT programs should not assume the window was created at the specified size or position.
// A GLUT program should use the window's reshape callback to determine the true size of the window."
void draw(const std::vector<Point> &points)
{
// glLineWidth(1.0f);
// Draw bike path
glBegin(GL_LINE_STRIP);
for(auto p : points)
{
auto val = (50 + (p.ele * 10)) / 180.0;
glColor3d(val, val, val);
glVertex3f(p.lat, p.ele, p.lon);
}
glEnd();
// usleep(100000);
glutPostRedisplay();
}
void draw_origin()
{
glBegin(GL_LINES);
// X:
glBegin(GL_LINE_STRIP);
glColor3d(0, 0, 0);
glVertex3f(-10.0f, 0.0f, 0.0f);
glColor3d(255, 0, 0);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glColor3d(0, 0, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// Y:
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, -10.0f, 0.0f);
glColor3d(0, 255, 0);
glVertex3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glColor3d(0, 0, 0);
glVertex3f(0.0f, 10.0f, 0.0f);
glEnd();
// Z:
glColor3d(0, 0, 255);
glBegin(GL_LINE_STRIP);
glVertex3f(0.0f, 0.0f, -10.0f);
glColor3d(0, 0, 255);
glVertex3f(0.0f, 0.0f, 0.0f);
glColor3d(0, 0, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
}
@ -136,12 +60,16 @@ void display()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glLineWidth(1.0f);
//camera.RotateYaw(0.01);
static double asdf = -10.0;
asdf += 0.02;
if(asdf > 15.0)
asdf = -15.0;
gluLookAt(-15, 12.0, -asdf, /* eye is at */
0.0, 6.0, 0.0, /* center is at */
gluLookAt(-15.0, 30.0, -asdf, /* eye is at */
0.0, 5.0, 0.0, /* center is at */
0.0, 1.0, 0.0); /* up is in positive Y direction */
draw_origin();
@ -197,18 +125,55 @@ int main(int argc, char *argv[])
}
for(auto file : files)
{
// NOTE(dev): OLD:
if(!ParseFile(tracks, file))
return -3; // couldn't parse file
ParseFile(tracks, file);
// NOTE(dev): NEW:
// TODO(dev): Xml Parser
// NORMALIZE TRACKS TO VIEWPORT:
bool first = true;
float min_lat, min_lon, min_ele, max_lat, max_lon, max_ele;
for(auto &track : tracks)
{
for(auto &p : track.points)
{
if(first)
{
first = false;
min_lat = max_lat = p.lat;
min_lon = max_lon = p.lon;
min_ele = max_ele = p.ele;
}
else
{
if(p.lat < min_lat)
min_lat = p.lat;
else if(p.lat > max_lat)
max_lat = p.lat;
if(p.lon < min_lon)
min_lon = p.lon;
else if(p.lon > max_lon)
max_lon = p.lon;
if(p.ele < min_ele)
min_ele = p.ele;
else if(p.ele > max_ele)
max_ele = p.ele;
}
}
}
auto lat_diff = min_lat + ((max_lat - min_lat) / 2.0);
auto lon_diff = min_lon + ((max_lon - min_lon) / 2.0);
auto ele_diff = min_ele;
for(auto &track : tracks)
{
for(auto &p : track.points)
{
p.lat -= lat_diff;
p.lon -= lon_diff;
p.ele -= ele_diff;
}
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA | GLUT_MULTISAMPLE);
glutInit(&argc, argv);
glutCreateWindow("test opengl program");
glutCreateWindow("3D GPX Viewer");
glutDisplayFunc(display);
// NOTE(dev): lmfao:
@ -216,6 +181,9 @@ int main(int argc, char *argv[])
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
init();
camera.Init();
camera.Fly(50);
camera.RotatePitch(-89 * M_PI / 180.0);
glutMainLoop();
return 0;

2596
rapidxml.hpp Executable file

File diff suppressed because it is too large Load Diff