Split up files. Added rapidxml for xml parsing.
This commit is contained in:
parent
a5175799ba
commit
40d41361fc
6
Makefile
6
Makefile
@ -1,2 +1,4 @@
|
|||||||
a.out: main.cpp
|
a.out: *.cpp
|
||||||
clang++ -std=c++17 -g -o a.out main.cpp -lGL -lGLU -lglut -lstdc++fs
|
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
152
Track.cpp
Normal 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
27
Track.h
Normal 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
26
Xml.cpp
Normal 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
13
Xml.h
Normal 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
172
main.cpp
@ -1,11 +1,13 @@
|
|||||||
#include "rapidxml.hpp"
|
#include "camera/Camera.h"
|
||||||
|
#include "Xml.h"
|
||||||
|
#include "Track.h"
|
||||||
|
|
||||||
#include <GL/glut.h>
|
#include <GL/glut.h>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h> // fmod
|
#include <math.h> // fmod
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -14,119 +16,41 @@
|
|||||||
GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
|
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. */
|
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
|
||||||
|
|
||||||
struct Point {
|
Camera camera;
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dev):
|
// TODO(dev):
|
||||||
// As per https://www.opengl.org/resources/libraries/glut/spec3/node11.html
|
// 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.
|
// "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."
|
// 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()
|
void draw_origin()
|
||||||
{
|
{
|
||||||
glBegin(GL_LINES);
|
|
||||||
|
|
||||||
// X:
|
// X:
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
glColor3d(0, 0, 0);
|
||||||
|
glVertex3f(-10.0f, 0.0f, 0.0f);
|
||||||
glColor3d(255, 0, 0);
|
glColor3d(255, 0, 0);
|
||||||
glVertex3f(-1.0f, 0.0f, 0.0f);
|
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||||
glColor3d(0, 0, 0);
|
glColor3d(0, 0, 0);
|
||||||
glVertex3f(10.0f, 0.0f, 0.0f);
|
glVertex3f(10.0f, 0.0f, 0.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
// Y:
|
// Y:
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
glVertex3f(0.0f, -10.0f, 0.0f);
|
||||||
glColor3d(0, 255, 0);
|
glColor3d(0, 255, 0);
|
||||||
glVertex3f(0.0f, -1.0f, 0.0f);
|
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||||
glColor3d(0, 0, 0);
|
glColor3d(0, 0, 0);
|
||||||
glVertex3f(0.0f, 10.0f, 0.0f);
|
glVertex3f(0.0f, 10.0f, 0.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
// Z:
|
// Z:
|
||||||
glColor3d(0, 0, 255);
|
glBegin(GL_LINE_STRIP);
|
||||||
glVertex3f(0.0f, 0.0f, -10.0f);
|
glVertex3f(0.0f, 0.0f, -10.0f);
|
||||||
|
glColor3d(0, 0, 255);
|
||||||
|
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||||
glColor3d(0, 0, 0);
|
glColor3d(0, 0, 0);
|
||||||
glVertex3f(0.0f, 0.0f, 10.0f);
|
glVertex3f(0.0f, 0.0f, 10.0f);
|
||||||
|
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,12 +60,16 @@ void display()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glLineWidth(1.0f);
|
||||||
|
|
||||||
|
//camera.RotateYaw(0.01);
|
||||||
|
|
||||||
static double asdf = -10.0;
|
static double asdf = -10.0;
|
||||||
asdf += 0.02;
|
asdf += 0.02;
|
||||||
if(asdf > 15.0)
|
if(asdf > 15.0)
|
||||||
asdf = -15.0;
|
asdf = -15.0;
|
||||||
gluLookAt(-15, 12.0, -asdf, /* eye is at */
|
gluLookAt(-15.0, 30.0, -asdf, /* eye is at */
|
||||||
0.0, 6.0, 0.0, /* center is at */
|
0.0, 5.0, 0.0, /* center is at */
|
||||||
0.0, 1.0, 0.0); /* up is in positive Y direction */
|
0.0, 1.0, 0.0); /* up is in positive Y direction */
|
||||||
|
|
||||||
draw_origin();
|
draw_origin();
|
||||||
@ -197,18 +125,55 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(auto file : files)
|
for(auto file : files)
|
||||||
{
|
ParseFile(tracks, file);
|
||||||
// NOTE(dev): OLD:
|
|
||||||
if(!ParseFile(tracks, file))
|
|
||||||
return -3; // couldn't parse file
|
|
||||||
|
|
||||||
// NOTE(dev): NEW:
|
// NORMALIZE TRACKS TO VIEWPORT:
|
||||||
// TODO(dev): Xml Parser
|
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);
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA | GLUT_MULTISAMPLE);
|
||||||
glutInit(&argc, argv);
|
glutInit(&argc, argv);
|
||||||
glutCreateWindow("test opengl program");
|
glutCreateWindow("3D GPX Viewer");
|
||||||
glutDisplayFunc(display);
|
glutDisplayFunc(display);
|
||||||
|
|
||||||
// NOTE(dev): lmfao:
|
// NOTE(dev): lmfao:
|
||||||
@ -216,6 +181,9 @@ int main(int argc, char *argv[])
|
|||||||
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
|
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
camera.Init();
|
||||||
|
camera.Fly(50);
|
||||||
|
camera.RotatePitch(-89 * M_PI / 180.0);
|
||||||
glutMainLoop();
|
glutMainLoop();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
2596
rapidxml.hpp
Executable file
2596
rapidxml.hpp
Executable file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user