{ /* NB! The program will only take a maximum of 10 000 000 bytes, as declaring a character array as a const int after .length() in root length is not allowed. This bug is denoted with *** in the script when it first appears. This project is about experimenting with data extraction from files, reorganizing data, and using this data to plot a path represented by the data. It will take on GPX-data from my Polar M430 watch and display the path taken in a 3D environment, making it easier for athletes to have a better way to consider elevation in potential exercise routes. Updates and improvements to the 3D path will be attempted. Among improvements are velocity notations in color format and elevation markings. */ // Lets the user decide which file to use string fileToRead; cout << "Enter a .txt file for the program to read:\t"; getline(cin, fileToRead); cout << "Processing..." << endl; // Making an input file stream object to be able to read saved data. ifstream gpxReadFile; gpxReadFile.open(fileToRead); // Short error message to spare the program from running a "bad" file // Will terminate the program if (gpxReadFile.fail()) { cerr << "Error opening file, please check for spelling errors etc.\n" << endl; exit(1); } // Defining a string-object that will denote the data to be parsed string gpxString; // NOTE! The program assumes the gpx-file to be as a .txt // file, where the data is stored as one single line. // Reads the file until its end // "While not end of file gpxReadFile" while (!gpxReadFile.eof()) { getline(gpxReadFile, gpxString); } // Now, gpxString is stored as a looong string object // This string object can now be fed to the parsing algorithm // This next piece of code will convert the string into a // char array. // Retrieving the length of the string first const int lengthData = gpxString.length(); // Making the character array with a fixed size. *** // char gpxCharArray[lengthData + 1]; won't work. char gpxCharArray[10000000]; // Copying the string data to gpxCharArray for(int i = 0;i < lengthData; i++) { gpxCharArray[i] = gpxString.at(i); } // Making the tagMatrix with a size the fraction of the number // of bytes the script reads. I figured 3 million rows out of potentially // 10 million characters should be enough to capture every tag. char tagMatrix[3000000][100]; // THIS SECTION PARSES THE GPX DATA // Predefining some constants before the main for loop checking if-statements for parsing int numTags = 0; int pos = 0; int nextTagCheck = 0; for (int i = 0; i < lengthData; i++) { if(gpxCharArray[i] == char(0)) break; // Checks if it has reached the end of the line if(gpxCharArray[i] == char(32)) continue; // Code for ignoring all spaces. (char(32) symbolizes the key space) if(nextTagCheck && gpxCharArray[i] == '<') {numTags++; pos = 0;} // Checks whether the next tag is about to start if(gpxCharArray[i] == '<') {nextTagCheck = 1; tagMatrix[numTags][pos] = gpxCharArray[i];pos++; continue;} // Marks a new tag if(nextTagCheck) {tagMatrix[numTags][pos] = gpxCharArray[i];pos++;} // Data inside the tags will be appended to the tagMatrix if(!nextTagCheck) {nextTagCheck = 1; tagMatrix[numTags][pos] = gpxCharArray[i];pos++;} // This line restores the nextTagCheck for the next iteration. if(gpxCharArray[i] == '>') {nextTagCheck = 0; numTags++; pos=0;} // End of a tag } cout << "\nParsing into a tag/token matrix complete\n"; // Defining the total number of points that will need to be extracted. // This number is very useful and will be used later on! int numOfPoints = (numTags - 18)/8; // Now the tagMatrix holds the gpx information in a much more // useful way of extracting data. Lucky for us, the data in this // format repeats itself as a linear function of row elements. // Extracting the x, y and z components of the tagMatrix // x and y repeat themselves in a fashion of 8x + 14, // whilst z repeats itself in a fashion of 8x + 16 // z lies in the row elements: // 16, 24, 32, 40, ... = 8x + 16 // As long as 8x + 16 < numTags - 4 // The -4 is there to be certain that // the iterations don't round up such that // the for loop obtains something that is not // elevation information. // To write to a list, I will have to predefine // the elevationPointTuple first. // Note that elevationPointTuple will consist // of MANY zeros, that will have to be remembered for // future statements double elePointTuple[3000000]; for (int k = 0; k < (numTags - 18)/8; k++) { elePointTuple[k] = atof(tagMatrix[8*k + 16]); } // x and y lies in the row elements: // 14, 22, 30, 38, ... = 8x + 14 // As long as 8x + 14 < numTags - 2 // Predefining tuples to be written to double latPointTuple[3000000]; double lonPointTuple[3000000]; // Defining what the code should look for when parsing // lines. char firstDoubleIndicator[] = " appears. char timeIndicator[] = "