Runways and Gates now with new read/write

This commit is contained in:
2022-09-10 01:07:00 +02:00
parent 2fc2170763
commit 94fbc1f558
27 changed files with 817 additions and 909 deletions
+26
View File
@@ -0,0 +1,26 @@
#include "simdata/gate.h"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
Gate::Gate(std::string designator,
struct germanairlinesva::geodata::point center,
std::uint8_t radius)
{
this->designator = designator;
this->center = center;
this->radius = radius;
}
void Gate::toFile(std::ofstream &out) const
{
writeString(out, this->designator);
write<struct germanairlinesva::geodata::point>(out, this->center);
write<std::uint8_t>(out, this->radius);
}
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
+3 -3
View File
@@ -25,10 +25,10 @@ namespace file
std::string line;
while (std::getline(config, line)) {
std::vector<std::string> fields =
germanairlinesva_util::split(line, '=');
germanairlinesva::util::split(line, '=');
if (fields.size() >= 2) {
germanairlinesva_util::trim(fields[0]);
germanairlinesva_util::trim(fields[1]);
germanairlinesva::util::trim(fields[0]);
germanairlinesva::util::trim(fields[1]);
settings[fields[0]] = fields[1];
}
}
+3 -3
View File
@@ -5,7 +5,7 @@
#include <cstring>
#include <vector>
#include "geodata.h"
#include "geodata.hpp"
namespace germanairlinesva
{
@@ -25,7 +25,7 @@ namespace file
std::uint32_t time = 0;
std::uint16_t altitude = 0;
std::uint16_t groundSpeed = 0;
struct germanairlinesva_geodata::point coordinates;
struct germanairlinesva::geodata::point coordinates;
std::vector<std::uint8_t> file;
public:
@@ -33,7 +33,7 @@ namespace file
RecordingEntry(std::uint32_t time,
std::uint16_t altitude,
std::uint16_t groundSpeed,
struct germanairlinesva_geodata::point coordinates);
struct germanairlinesva::geodata::point coordinates);
inline const std::uint8_t *getBinaryData() const { return file.data(); }
inline std::size_t getBinaryLength() const { return file.size(); }
+67
View File
@@ -0,0 +1,67 @@
#ifndef GERMANAIRLINESVA_FILE_GATE_H
#define GERMANAIRLINESVA_FILE_GATE_H
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include "geodata.hpp"
#include "helpers.hpp"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
/*
* Representation of gate
* Heading in degrees (0...360)
* Radius in metres
*
* Designator must be null terminated
*
* UINT8 | CHAR[] | POINT | UINT8
* -------+------------+--------+-------
* STRLEN | DESIGNATOR | CENTER | RADIUS
*/
class Gate
{
private:
std::string designator;
struct germanairlinesva::geodata::point center;
std::uint8_t radius;
public:
Gate(std::string designator,
struct germanairlinesva::geodata::point center,
std::uint8_t radius);
void toFile(std::ofstream &out) const;
inline const std::string to_string() const
{
std::ostringstream str;
str << "Gate " << this->designator << " at " << this->center.latitude
<< "N " << this->center.longitude << "E, Radius "
<< (int)this->radius;
return str.str();
}
friend inline std::ostream &operator<<(std::ostream &os,
const Gate &gate)
{
return os << gate.to_string();
}
};
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+87
View File
@@ -0,0 +1,87 @@
#ifndef GERMANAIRLINESVA_FILE_RUNWAY_H
#define GERMANAIRLINESVA_FILE_RUNWAY_H
#include <fstream>
#include <iomanip>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <utility>
#include "geodata.hpp"
#include "helpers.hpp"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
/*
* Representation of one runway with supplementary information
* Heading in degrees (0...360) true
* Width and length in meters
*
* Designator must be null terminated
*
* UINT8 | CHAR[] | BOX | UINT8 | UINT16 | UINT16
* -------+------------+--------+-------+--------+-------
* STRLEN | DESIGNATOR | BOUNDS | WIDTH | LENGTH | TRUHDG
*/
class Runway
{
private:
std::string designator;
struct germanairlinesva::geodata::box bounds;
std::uint8_t width;
std::uint16_t length;
std::uint16_t trueHeading;
std::vector<std::uint8_t> file;
public:
// From X-Plane or MakeRwys
Runway(std::string designator,
double latitudeStart,
double longitudeStart,
double latitudeEnd,
double longitudeEnd,
double width);
// From database
Runway(std::string designator,
struct germanairlinesva::geodata::box bounds,
std::uint8_t width,
std::uint16_t length,
std::uint16_t trueHeading);
void toFile(std::ofstream &out) const;
inline const std::string to_string() const
{
std::ostringstream str;
str << "Runway " << this->designator << " with bounds "
<< this->bounds.topLeft.latitude << "N "
<< this->bounds.topLeft.longitude << "E, "
<< this->bounds.topRight.latitude << "N "
<< this->bounds.topRight.longitude << "E, "
<< this->bounds.bottomRight.latitude << "N "
<< this->bounds.bottomRight.longitude << "E, "
<< this->bounds.bottomLeft.latitude << "N "
<< this->bounds.bottomLeft.longitude << "E, "
<< "Width " << (int)this->width << "m, Length " << this->length
<< "m, True Heading " << this->trueHeading << "°";
return str.str();
}
friend inline std::ostream &operator<<(std::ostream &os,
const Runway &runway)
{
return os << runway.to_string();
}
};
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef GERMANAIRLINESVA_FILE_SIMDATAXP_H
#define GERMANAIRLINESVA_FILE_SIMDATAXP_H
#include <fstream>
#include <map>
#include <string>
#include "simdata/gate.h"
#include "simdata/runway.h"
#include "util.hpp"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
int scan(
const std::string defaultFile,
const std::string sceneryPack,
const std::string logFile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports);
void makeAirport(
const std::string &kind,
std::ifstream &infile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports,
std::ofstream &logfile);
void makeGate15(std::vector<Gate> &gates,
const std::vector<std::string> &fields);
void makeRunway(std::vector<Runway> &runways,
const std::vector<std::string> &fields);
void makeGate1300(std::vector<Gate> &gates,
const std::vector<std::string> &fields);
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+174
View File
@@ -0,0 +1,174 @@
#ifndef GERMANAIRLINESVA_FILE_SIMULATORDATABASE_H
#define GERMANAIRLINESVA_FILE_SIMULATORDATABASE_H
#include <cstdint>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "simdata/gate.h"
#include "simdata/runway.h"
/*
* Header
*
* CHAR[5] | UINT8
* --------+--------
* VGAS | VERSION
*/
/*
* Airport
*
* UINT8 | CHAR[] | UINT16 | GATE[] | UINT8 | RUNWAY[]
* --------+--------+----------+--------+---------+---------
* STRLEN | ICAO | NUMGATES | GATES | NUMRWYS | RUNWAYS
*/
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
static inline void toFile(
std::map<
std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
&airports,
const std::string &file)
{
std::uint8_t null = 0;
std::ofstream out(file, std::fstream::binary);
// File Header, Last member is version
std::uint8_t header[] = {'V', 'G', 'A', 'S', '\0', 1};
out.write(reinterpret_cast<const char *>(header), 6);
// Num Airports
std::uint16_t numAirports = airports.size();
out.write(reinterpret_cast<const char *>(&numAirports),
sizeof(numAirports));
// Airport
for (const std::pair<
const std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
&airport : airports) {
std::string icao = airport.first;
std::vector<germanairlinesva::file::simdata::Gate> gates =
airport.second.first;
std::vector<germanairlinesva::file::simdata::Runway> runways =
airport.second.second;
// ICAO
std::uint8_t icaoLength = icao.length();
out.write(reinterpret_cast<const char *>(&icaoLength),
sizeof(icaoLength));
out.write(icao.c_str(), icaoLength);
out.write(reinterpret_cast<const char *>(&null), sizeof(null));
// Gates
std::uint16_t numGates = gates.size();
out.write(reinterpret_cast<const char *>(&numGates), sizeof(numGates));
for (germanairlinesva::file::simdata::Gate &gate : gates) {
gate.toFile(out);
}
// Runways
std::uint8_t numRunways = runways.size();
out.write(reinterpret_cast<const char *>(&numRunways),
sizeof(numRunways));
for (germanairlinesva::file::simdata::Runway &runway : runways) {
runway.toFile(out);
}
}
out.close();
}
static inline std::map<
std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
readVersion1(std::ifstream &in)
{
std::map<std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
airports;
std::uint16_t numAirports;
in.read(reinterpret_cast<char *>(&numAirports), sizeof(numAirports));
for (int i = 0; i < numAirports; i++) {
// ICAO
std::uint8_t icaoLength;
in.read(reinterpret_cast<char *>(&icaoLength), sizeof(icaoLength));
char *icao = static_cast<char *>(calloc(icaoLength + 1, sizeof(char)));
in.read(icao, icaoLength + 1);
// Gates
std::uint16_t numGates;
in.read(reinterpret_cast<char *>(&numGates), sizeof(numGates));
for (int j = 0; j < numGates; j++) {
std::string designator = readString(in);
struct germanairlinesva::geodata::point center =
read<struct germanairlinesva::geodata::point>(in);
std::uint8_t radius = read<std::uint8_t>(in);
airports[icao].first.emplace_back(designator, center, radius);
}
// Runways
std::uint8_t numRunways;
in.read(reinterpret_cast<char *>(&numRunways), sizeof(numRunways));
for (int j = 0; j < numRunways; j++) {
std::string designator = readString(in);
// Bounds
struct germanairlinesva::geodata::box bounds =
read<struct germanairlinesva::geodata::box>(in);
std::uint8_t width = read<std::uint8_t>(in);
std::uint16_t length = read<std::uint16_t>(in);
std::uint16_t trueHeading = read<std::uint16_t>(in);
airports[icao].second.emplace_back(designator,
bounds,
width,
length,
trueHeading);
}
}
in.close();
return airports;
}
static inline std::map<
std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
fromFile(const std::string &file)
{
std::map<std::string,
std::pair<std::vector<germanairlinesva::file::simdata::Gate>,
std::vector<germanairlinesva::file::simdata::Runway>>>
airports;
std::ifstream in(file, std::ifstream::binary);
// File Header
char ident[5];
in.read(ident, 5);
if (strcmp(ident, "VGAS") != 0) {
throw std::invalid_argument("Wrong file");
}
std::uint8_t version;
in.read(reinterpret_cast<char *>(&version), 1);
if (version == 1) {
return readVersion1(in);
}
return airports;
}
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
#endif
+1 -1
View File
@@ -8,7 +8,7 @@ namespace file
{
Logbook::Logbook()
{
if (germanairlinesva_util::fileExists(XPLANE_PLUGIN_DIRECTORY LOGBOOK)) {
if (germanairlinesva::util::fileExists(XPLANE_PLUGIN_DIRECTORY LOGBOOK)) {
this->fromFile(XPLANE_PLUGIN_DIRECTORY LOGBOOK);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ namespace file
std::uint32_t time,
std::uint16_t altitude,
std::uint16_t groundSpeed,
struct germanairlinesva_geodata::point coordinates)
struct germanairlinesva::geodata::point coordinates)
{
this->time = time;
this->altitude = altitude;
+57
View File
@@ -0,0 +1,57 @@
#include "simdata/runway.h"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
Runway::Runway(std::string designator,
double latitudeStart,
double longitudeStart,
double latitudeEnd,
double longitudeEnd,
double width)
{
this->designator = designator;
this->width = width;
this->length = germanairlinesva::geodata::distanceEarthD(latitudeStart,
longitudeStart,
latitudeEnd,
longitudeEnd);
this->trueHeading = (std::uint16_t)std::round(
germanairlinesva::geodata::bearingDD(latitudeStart,
longitudeStart,
latitudeEnd,
longitudeEnd));
this->bounds = germanairlinesva::geodata::calculateBoxDD(
{latitudeStart, longitudeStart},
{latitudeEnd, longitudeEnd},
this->trueHeading,
this->width);
}
Runway::Runway(std::string designator,
germanairlinesva::geodata::box bounds,
std::uint8_t width,
std::uint16_t length,
std::uint16_t trueHeading)
{
this->designator = designator;
this->bounds = bounds;
this->width = width;
this->length = length;
this->trueHeading = trueHeading;
}
void Runway::toFile(std::ofstream &out) const
{
writeString(out, this->designator);
write<struct germanairlinesva::geodata::box>(out, this->bounds);
write<std::uint8_t>(out, this->width);
write<std::uint16_t>(out, this->length);
write<std::uint16_t>(out, this->trueHeading);
}
} // namespace simdata
} // namespace file
} // namespace germanairlinesva
+198
View File
@@ -0,0 +1,198 @@
#include "simdata/simdataXP.h"
namespace germanairlinesva
{
namespace file
{
namespace simdata
{
int scan(
const std::string defaultFile,
const std::string sceneryPack,
const std::string logFile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports)
{
std::ifstream base(defaultFile);
if (!base.good()) {
return 1;
}
std::ifstream custom(sceneryPack);
if (!custom.good()) {
base.close();
return 2;
}
std::ofstream logfile(logFile, std::fstream::trunc);
if (!logfile.good()) {
base.close();
custom.close();
return 3;
}
// Default
logfile << "<FILE> " << defaultFile << std::endl;
makeAirport("DEFAULT", base, airports, logfile);
base.close();
std::string line;
size_t pos;
std::vector<std::string> packs;
while (std::getline(custom, line)) {
if ((pos = line.find("SCENERY_PACK")) != std::string::npos) {
std::string path =
germanairlinesva::util::rtrim_copy(line.substr(pos + 13)) +
"Earth nav data/apt.dat";
packs.emplace_back(path);
}
}
std::reverse(packs.begin(), packs.end());
for (std::string const &path : packs) {
std::ifstream pack(path);
if (pack.good()) {
logfile << "<FILE> " << path << std::endl;
makeAirport("CUSTOM", pack, airports, logfile);
pack.close();
} else {
pack.close();
logfile << "<STATUS>"
<< "Could not find " << path << std::endl;
}
}
logfile << std::endl
<< "<STATUS> Total airports: " << airports.size() << std::endl;
custom.close();
logfile.close();
return 0;
}
void makeAirport(
const std::string &kind,
std::ifstream &infile,
std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
&airports,
std::ofstream &logfile)
{
std::string line;
std::string *currentIcao = nullptr;
std::vector<Gate> tmpGates;
std::vector<Runway> tmpRunways;
int apCount = 0;
int validCount = 0;
while (std::getline(infile, line)) {
std::vector<std::string> fields =
germanairlinesva::util::split(line, ' ');
fields = germanairlinesva::util::select_T<std::string>(
fields,
[](const std::string &s) { return s.length() > 0; });
if (fields.empty())
continue;
if (fields[0] == "1") {
// Write to file if ICAO is valid, and we have gates and runways
if (currentIcao != nullptr && !tmpRunways.empty() &&
!tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed"
<< std::endl;
} else if (currentIcao != nullptr) {
logfile << "\t<STATUS> " << *currentIcao
<< " had no gates or runways" << std::endl;
}
tmpGates = std::vector<Gate>();
tmpRunways = std::vector<Runway>();
currentIcao = new std::string(fields[4]);
apCount += 1;
logfile << "\t<" << kind << "> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "15") {
makeGate15(tmpGates, fields);
logfile << "\t\t<GATE OLD> " << line << std::endl;
} else if (fields[0] == "16" || fields[0] == "17") {
// Write to file if ICAO is valid, and we have gates and runways
if (currentIcao != nullptr && !tmpRunways.empty() &&
!tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed"
<< std::endl;
} else if (currentIcao != nullptr) {
logfile << "\t<STATUS> " << *currentIcao
<< " had no gates or runways" << std::endl;
}
tmpGates = std::vector<Gate>();
tmpRunways = std::vector<Runway>();
currentIcao = nullptr;
logfile << "\t<" << kind << " SKIPPED> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "100") {
makeRunway(tmpRunways, fields);
logfile << "\t\t<RUNWAY> " << line << std::endl;
} else if (currentIcao != nullptr && fields[0] == "1300") {
makeGate1300(tmpGates, fields);
logfile << "\t\t<GATE> " << line << std::endl;
}
}
if (currentIcao != nullptr && !tmpRunways.empty() && !tmpGates.empty()) {
airports[*currentIcao] = {tmpGates, tmpRunways};
validCount += 1;
logfile << "\t<STATUS> " << *currentIcao << " committed" << std::endl;
}
logfile << "<STATUS> " << apCount << " airports found, of which "
<< validCount << " are valid" << std::endl;
}
void makeGate15(std::vector<Gate> &gates,
const std::vector<std::string> &fields)
{
std::string gateName;
for (size_t j = 4; j < fields.size() - 1; j++) {
gateName += fields[j] + " ";
}
gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0");
struct germanairlinesva::geodata::point pt {
std::stod(fields[1]), std::stod(fields[2])
};
gates.emplace_back(gateName, pt, 40);
}
void makeRunway(std::vector<Runway> &runways,
const std::vector<std::string> &fields)
{
runways.emplace_back(fields[8],
std::stod(fields[9]),
std::stod(fields[10]),
std::stod(fields[18]),
std::stod(fields[19]),
std::stod(fields[1]));
runways.emplace_back(fields[17],
std::stod(fields[18]),
std::stod(fields[19]),
std::stod(fields[9]),
std::stod(fields[10]),
std::stod(fields[1]));
}
void makeGate1300(std::vector<Gate> &gates,
const std::vector<std::string> &fields)
{
std::string gateName;
for (size_t j = 6; j < fields.size() - 1; j++) {
gateName += fields[j] + " ";
}
gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0");
struct germanairlinesva::geodata::point pt {
std::stod(fields[1]), std::stod(fields[2])
};
gates.emplace_back(gateName, pt, 40);
}
} // namespace simdata
} // namespace file
} // namespace germanairlinesva