Namespaces
Better File handling
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
file(GLOB simdata CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/simdata/*.cpp)
|
||||
|
||||
add_library(simdata SHARED
|
||||
${simdata}
|
||||
)
|
||||
|
||||
target_include_directories(simdata PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/simdata/include
|
||||
${CMAKE_SOURCE_DIR}/utilities/include
|
||||
)
|
||||
|
||||
set_target_properties(simdata PROPERTIES
|
||||
PUBLIC_HEADER ${CMAKE_SOURCE_DIR}/simdata/include
|
||||
)
|
||||
target_compile_definitions(simdata PRIVATE
|
||||
_USE_MATH_DEFINES
|
||||
)
|
||||
target_compile_options(simdata PRIVATE
|
||||
-Wall
|
||||
-Wextra
|
||||
-pedantic
|
||||
)
|
||||
if(DEBUG)
|
||||
target_compile_options(simdata PRIVATE
|
||||
-g
|
||||
)
|
||||
target_link_options(simdata PRIVATE
|
||||
-g
|
||||
)
|
||||
else()
|
||||
target_compile_options(simdata PRIVATE
|
||||
-O2
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
message("Building simdata for MacOSX Universal into ${PROJECT_BINARY_DIR}/${PLUGIN_NAME}")
|
||||
|
||||
set_target_properties(simdata PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Plugin/${PLUGIN_NAME}"
|
||||
BUILD_WITH_INSTALL_NAME_DIR TRUE
|
||||
)
|
||||
|
||||
target_compile_options(simdata PRIVATE
|
||||
"SHELL:-arch i386"
|
||||
"SHELL:-arch x86_64"
|
||||
)
|
||||
target_link_options(simdata PRIVATE
|
||||
"SHELL:-arch i386"
|
||||
"SHELL:-arch x86_64"
|
||||
)
|
||||
target_link_libraries(simdata PRIVATE
|
||||
"-framework Security"
|
||||
)
|
||||
elseif(UNIX)
|
||||
message("Building simdata for Linux ${BIT} into ${PROJECT_BINARY_DIR}/Plugin/${PLUGIN_NAME}/${BIT}")
|
||||
|
||||
set_target_properties(simdata PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Plugin/${PLUGIN_NAME}/${BIT}"
|
||||
)
|
||||
|
||||
target_compile_options(simdata PRIVATE
|
||||
-nodefaultlibs
|
||||
)
|
||||
if(BIT STREQUAL "32")
|
||||
target_compile_options(simdata PRIVATE
|
||||
-m32
|
||||
)
|
||||
target_link_options(simdata PRIVATE
|
||||
-m32
|
||||
)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
message("Building simdata for Windows ${BIT} into ${PROJECT_BINARY_DIR}/Plugin/${PLUGIN_NAME}/${BIT}")
|
||||
|
||||
set_target_properties(simdata PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Plugin/${PLUGIN_NAME}/${BIT}"
|
||||
)
|
||||
|
||||
if(DEBUG)
|
||||
target_compile_options(simdata PRIVATE
|
||||
-gcodeview
|
||||
)
|
||||
target_link_options(simdata PRIVATE
|
||||
-Wl,-pdb=
|
||||
)
|
||||
endif()
|
||||
target_link_options(simdata PRIVATE
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "gate.h"
|
||||
|
||||
namespace germanairlinesva_simdata
|
||||
{
|
||||
Gate::Gate(const std::string &designator,
|
||||
double latitude,
|
||||
double longitude,
|
||||
std::uint8_t radius)
|
||||
{
|
||||
this->designator = designator;
|
||||
this->center = {latitude, longitude};
|
||||
this->radius = radius;
|
||||
|
||||
file = std::vector<std::uint8_t>(1 + this->designator.length() + 1 +
|
||||
sizeof(center) + sizeof(radius),
|
||||
0);
|
||||
std::uint8_t *bufPtr = file.data();
|
||||
memset(bufPtr,
|
||||
static_cast<std::uint8_t>(this->designator.length()),
|
||||
sizeof(std::uint8_t));
|
||||
bufPtr++;
|
||||
memcpy(bufPtr, this->designator.c_str(), this->designator.length());
|
||||
bufPtr += this->designator.length() + 1;
|
||||
memcpy(bufPtr, &this->center, sizeof(this->center));
|
||||
bufPtr += sizeof(this->center);
|
||||
memcpy(bufPtr, &this->radius, sizeof(this->radius));
|
||||
}
|
||||
|
||||
// From database
|
||||
Gate::Gate(const std::string &designator,
|
||||
germanairlinesva_geodata::point center,
|
||||
std::uint8_t radius)
|
||||
{
|
||||
this->designator = designator;
|
||||
this->center = center;
|
||||
this->radius = radius;
|
||||
|
||||
file = std::vector<std::uint8_t>(1 + this->designator.length() + 1 +
|
||||
sizeof(center) + sizeof(radius),
|
||||
0);
|
||||
std::uint8_t *bufPtr = file.data();
|
||||
memset(bufPtr,
|
||||
static_cast<std::uint8_t>(this->designator.length()),
|
||||
sizeof(std::uint8_t));
|
||||
bufPtr++;
|
||||
memcpy(bufPtr, this->designator.c_str(), this->designator.length());
|
||||
bufPtr += this->designator.length() + 1;
|
||||
memcpy(bufPtr, &this->center, sizeof(this->center));
|
||||
bufPtr += sizeof(this->center);
|
||||
memcpy(bufPtr, &this->radius, sizeof(this->radius));
|
||||
}
|
||||
} // namespace germanairlinesva_simdata
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef GERMANAIRLINESVA_GACONNECTOR_GATE_H
|
||||
#define GERMANAIRLINESVA_GACONNECTOR_GATE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "geodata.h"
|
||||
|
||||
namespace germanairlinesva_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;
|
||||
germanairlinesva_geodata::point center;
|
||||
std::uint8_t radius;
|
||||
std::vector<std::uint8_t> file;
|
||||
|
||||
public:
|
||||
// From X-Plane or MakeRwys
|
||||
Gate(const std::string &designator,
|
||||
double latitude,
|
||||
double longitude,
|
||||
std::uint8_t radius);
|
||||
// From database
|
||||
Gate(const std::string &designator,
|
||||
germanairlinesva_geodata::point center,
|
||||
std::uint8_t radius);
|
||||
|
||||
std::uint8_t *getBinaryData() { return file.data(); }
|
||||
std::size_t getBinaryLength() { return file.size(); }
|
||||
|
||||
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 std::ostream &operator<<(std::ostream &os, const Gate &gate);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const Gate &gate)
|
||||
{
|
||||
return os << gate.to_string();
|
||||
}
|
||||
} // namespace germanairlinesva_simdata
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
#ifndef GERMANAIRLINESVA_GACONNECTOR_GEODATA_H
|
||||
#define GERMANAIRLINESVA_GACONNECTOR_GEODATA_H
|
||||
|
||||
#ifdef IBM
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#define BUFSIZE 1024
|
||||
#define MD5LEN 16
|
||||
#define EARTH_M 6371000
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
namespace germanairlinesva_geodata
|
||||
{
|
||||
struct point {
|
||||
double latitude;
|
||||
double longitude;
|
||||
};
|
||||
|
||||
struct box {
|
||||
struct point topLeft;
|
||||
struct point topRight;
|
||||
struct point bottomRight;
|
||||
struct point bottomLeft;
|
||||
};
|
||||
|
||||
static inline double toFeet(double value) { return value * 3.280839895; }
|
||||
|
||||
static inline double toDegrees(double value) { return value * 180 / M_PI; }
|
||||
|
||||
static inline double toRadians(double value) { return value * M_PI / 180; }
|
||||
|
||||
static inline double normalize(double value)
|
||||
{
|
||||
return fmod(value + 360, 360);
|
||||
}
|
||||
|
||||
// Input and Output in degrees
|
||||
static inline double bearingDD(double fromLatitude,
|
||||
double fromLongitude,
|
||||
double toLatitude,
|
||||
double toLongitude)
|
||||
{
|
||||
double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) *
|
||||
cos(toRadians(toLatitude));
|
||||
double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) -
|
||||
sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) *
|
||||
cos(toRadians(toLongitude) - toRadians(fromLongitude));
|
||||
|
||||
return normalize(toDegrees(atan2(y, x)));
|
||||
}
|
||||
|
||||
// Input in degrees, Output in metres
|
||||
static inline double distanceEarthD(double fromLatitude,
|
||||
double fromLongitude,
|
||||
double toLatitude,
|
||||
double toLongitude)
|
||||
{
|
||||
double lat1r, lon1r, lat2r, lon2r, u, v;
|
||||
lat1r = toRadians(fromLatitude);
|
||||
lon1r = toRadians(fromLongitude);
|
||||
lat2r = toRadians(toLatitude);
|
||||
lon2r = toRadians(toLongitude);
|
||||
u = sin((lat2r - lat1r) / 2);
|
||||
v = sin((lon2r - lon1r) / 2);
|
||||
return 2.0 * EARTH_M * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
|
||||
}
|
||||
|
||||
// Input and Output in degrees
|
||||
static inline struct point calculatePointDD(struct point coordinates,
|
||||
double bearing,
|
||||
double distance)
|
||||
{
|
||||
double r_latitude = toRadians(coordinates.latitude);
|
||||
double r_longitude = toRadians(coordinates.longitude);
|
||||
double r_bearing = toRadians(bearing);
|
||||
|
||||
double newLatitude =
|
||||
std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) +
|
||||
std::cos(r_latitude) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_bearing));
|
||||
double newLongitude =
|
||||
r_longitude +
|
||||
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_latitude),
|
||||
std::cos(distance / EARTH_M) -
|
||||
std::sin(r_latitude) * std::sin(newLatitude));
|
||||
|
||||
return {toDegrees(newLatitude), toDegrees(newLongitude)};
|
||||
}
|
||||
|
||||
// Input in degrees, Output in radians
|
||||
static inline struct point calculatePointDR(struct point coordinates,
|
||||
double bearing,
|
||||
double distance)
|
||||
{
|
||||
double r_latitude = toRadians(coordinates.latitude);
|
||||
double r_longitude = toRadians(coordinates.longitude);
|
||||
double r_bearing = toRadians(bearing);
|
||||
|
||||
double newLatitude =
|
||||
std::asin(std::sin(r_latitude) * std::cos(distance / EARTH_M) +
|
||||
std::cos(r_latitude) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_bearing));
|
||||
double newLongitude =
|
||||
r_longitude +
|
||||
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_latitude),
|
||||
std::cos(distance / EARTH_M) -
|
||||
std::sin(r_latitude) * std::sin(newLatitude));
|
||||
|
||||
return {newLatitude, newLongitude};
|
||||
}
|
||||
|
||||
// LAT/LON in radians, BEARING/Output in degrees
|
||||
static inline struct point calculatePointRD(struct point coordinates,
|
||||
double bearing,
|
||||
double distance)
|
||||
{
|
||||
double r_bearing = toRadians(bearing);
|
||||
|
||||
double newLatitude = std::asin(
|
||||
std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) +
|
||||
std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_bearing));
|
||||
double newLongitude =
|
||||
coordinates.longitude +
|
||||
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
|
||||
std::cos(coordinates.latitude),
|
||||
std::cos(distance / EARTH_M) -
|
||||
std::sin(coordinates.latitude) * std::sin(newLatitude));
|
||||
|
||||
return {toDegrees(newLatitude), toDegrees(newLongitude)};
|
||||
}
|
||||
|
||||
// LAT/LON/Output in radians, BEARING in degrees
|
||||
static inline struct point calculatePointRR(struct point coordinates,
|
||||
double bearing,
|
||||
double distance)
|
||||
{
|
||||
double r_bearing = toRadians(bearing);
|
||||
|
||||
double newLatitude = std::asin(
|
||||
std::sin(coordinates.latitude) * std::cos(distance / EARTH_M) +
|
||||
std::cos(coordinates.latitude) * std::sin(distance / EARTH_M) *
|
||||
std::cos(r_bearing));
|
||||
double newLongitude =
|
||||
coordinates.longitude +
|
||||
std::atan2(std::sin(r_bearing) * std::sin(distance / EARTH_M) *
|
||||
std::cos(coordinates.latitude),
|
||||
std::cos(distance / EARTH_M) -
|
||||
std::sin(coordinates.latitude) * std::sin(newLatitude));
|
||||
|
||||
return {newLatitude, newLongitude};
|
||||
}
|
||||
|
||||
// Input in degrees, calculate from center
|
||||
static inline box calculateBoxDD(struct point center,
|
||||
double bearing,
|
||||
double length,
|
||||
double width)
|
||||
{
|
||||
struct point primaryCenter = calculatePointDR(center, bearing, -length / 2);
|
||||
struct point secondaryCenter =
|
||||
calculatePointDR(center, bearing, length / 2);
|
||||
double offsetHeadingNorth =
|
||||
bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360;
|
||||
struct point primaryTop =
|
||||
calculatePointRD(primaryCenter, offsetHeadingNorth, width / 2);
|
||||
struct point primaryBottom =
|
||||
calculatePointRD(primaryCenter, offsetHeadingNorth, -width / 2);
|
||||
struct point secondaryTop =
|
||||
calculatePointRD(secondaryCenter, offsetHeadingNorth, width / 2);
|
||||
struct point secondaryBottom =
|
||||
calculatePointRD(secondaryCenter, offsetHeadingNorth, -width / 2);
|
||||
|
||||
return {primaryTop, secondaryTop, secondaryBottom, primaryBottom};
|
||||
}
|
||||
|
||||
// Input in degrees, calculate from start end
|
||||
static inline box calculateBoxDD(struct point start,
|
||||
struct point end,
|
||||
double bearing,
|
||||
double width)
|
||||
{
|
||||
double offsetHeadingNorth =
|
||||
bearing - 90 > 0 ? bearing - 90 : bearing - 90 + 360;
|
||||
struct point primaryTop =
|
||||
calculatePointDD(start, offsetHeadingNorth, width / 2);
|
||||
struct point primaryBottom =
|
||||
calculatePointDD(start, offsetHeadingNorth, -width / 2);
|
||||
struct point secondaryTop =
|
||||
calculatePointDD(end, offsetHeadingNorth, width / 2);
|
||||
struct point secondaryBottom =
|
||||
calculatePointDD(end, offsetHeadingNorth, -width / 2);
|
||||
|
||||
return {primaryTop, secondaryTop, secondaryBottom, primaryBottom};
|
||||
}
|
||||
|
||||
} // namespace germanairlinesva_geodata
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef GERMANAIRLINESVA_GACONNECTOR_RUNWAY_H
|
||||
#define GERMANAIRLINESVA_GACONNECTOR_RUNWAY_H
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "geodata.h"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace germanairlinesva_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);
|
||||
|
||||
std::uint8_t *getBinaryData() { return file.data(); }
|
||||
std::size_t getBinaryLength() { return file.size(); }
|
||||
|
||||
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 std::ostream &operator<<(std::ostream &os, const Runway &runway);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const Runway &runway)
|
||||
{
|
||||
return os << runway.to_string();
|
||||
}
|
||||
} // namespace germanairlinesva_simdata
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef GERMANAIRLINESVA_GACONNECTOR_SIMDATA_H
|
||||
#define GERMANAIRLINESVA_GACONNECTOR_SIMDATA_H
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "gate.h"
|
||||
#include "runway.h"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace germanairlinesva_simdata
|
||||
{
|
||||
int scan(
|
||||
const char *defaultFile,
|
||||
const char *sceneryPack,
|
||||
const char *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, std::vector<std::string> fields);
|
||||
void makeRunway(std::vector<Runway> *runways,
|
||||
std::vector<std::string> fields);
|
||||
void makeGate1300(std::vector<Gate> *gates, std::vector<std::string> fields);
|
||||
|
||||
} // namespace germanairlinesva_simdata
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,191 @@
|
||||
#ifndef GERMANAIRLINESVA_GACONNECTOR_SIMULATORDATABASE_H
|
||||
#define GERMANAIRLINESVA_GACONNECTOR_SIMULATORDATABASE_H
|
||||
|
||||
#include "gate.h"
|
||||
#include "runway.h"
|
||||
|
||||
#define CURRENT_VERSION 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* Header
|
||||
*
|
||||
* CHAR[5] | UINT8
|
||||
* --------+--------
|
||||
* VGAS | VERSION
|
||||
*/
|
||||
/*
|
||||
* Airport
|
||||
*
|
||||
* UINT8 | CHAR[] | UINT16 | GATE[] | UINT8 | RUNWAY[]
|
||||
* --------+--------+----------+--------+---------+---------
|
||||
* STRLEN | ICAO | NUMGATES | GATES | NUMRWYS | RUNWAYS
|
||||
*/
|
||||
|
||||
namespace germanairlinesva_simdata
|
||||
{
|
||||
static inline void
|
||||
toFile(std::map<std::string,
|
||||
std::pair<std::vector<germanairlinesva_simdata::Gate>,
|
||||
std::vector<germanairlinesva_simdata::Runway>>>
|
||||
&airports,
|
||||
const std::string &file)
|
||||
{
|
||||
std::uint8_t null = 0;
|
||||
std::ofstream out(file, std::fstream::binary);
|
||||
|
||||
// File Header
|
||||
std::uint8_t header[] = {'V', 'G', 'A', 'S', 0, CURRENT_VERSION};
|
||||
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_simdata::Gate>,
|
||||
std::vector<germanairlinesva_simdata::Runway>>>
|
||||
&airport : airports) {
|
||||
std::string icao = airport.first;
|
||||
std::vector<germanairlinesva_simdata::Gate> gates = airport.second.first;
|
||||
std::vector<germanairlinesva_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_simdata::Gate &gate : gates) {
|
||||
out.write(reinterpret_cast<const char *>(gate.getBinaryData()),
|
||||
(std::streamsize)gate.getBinaryLength());
|
||||
}
|
||||
// Runways
|
||||
std::uint8_t numRunways = runways.size();
|
||||
out.write(reinterpret_cast<const char *>(&numRunways),
|
||||
sizeof(numRunways));
|
||||
for (germanairlinesva_simdata::Runway &runway : runways) {
|
||||
out.write(reinterpret_cast<const char *>(runway.getBinaryData()),
|
||||
(std::streamsize)runway.getBinaryLength());
|
||||
}
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
static inline std::map<
|
||||
std::string,
|
||||
std::pair<std::vector<germanairlinesva_simdata::Gate>,
|
||||
std::vector<germanairlinesva_simdata::Runway>>>
|
||||
readVersion1(std::ifstream &in)
|
||||
{
|
||||
std::map<std::string,
|
||||
std::pair<std::vector<germanairlinesva_simdata::Gate>,
|
||||
std::vector<germanairlinesva_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++) {
|
||||
// ICAO
|
||||
std::uint8_t designatorLength;
|
||||
in.read(reinterpret_cast<char *>(&designatorLength),
|
||||
sizeof(designatorLength));
|
||||
char *designator =
|
||||
static_cast<char *>(calloc(designatorLength + 1, sizeof(char)));
|
||||
in.read(designator, designatorLength + 1);
|
||||
// Center
|
||||
germanairlinesva_geodata::point center;
|
||||
in.read(reinterpret_cast<char *>(¢er), sizeof(center));
|
||||
// Radius
|
||||
std::uint8_t radius;
|
||||
in.read(reinterpret_cast<char *>(&radius), sizeof(radius));
|
||||
|
||||
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++) {
|
||||
// ICAO
|
||||
std::uint8_t designatorLength;
|
||||
in.read(reinterpret_cast<char *>(&designatorLength),
|
||||
sizeof(designatorLength));
|
||||
char *designator =
|
||||
static_cast<char *>(calloc(designatorLength + 1, sizeof(char)));
|
||||
in.read(designator, designatorLength + 1);
|
||||
// Bounds
|
||||
germanairlinesva_geodata::box bounds;
|
||||
in.read(reinterpret_cast<char *>(&bounds), sizeof(bounds));
|
||||
// Width
|
||||
std::uint8_t width;
|
||||
in.read(reinterpret_cast<char *>(&width), sizeof(width));
|
||||
// Length
|
||||
std::uint16_t length;
|
||||
in.read(reinterpret_cast<char *>(&length), sizeof(length));
|
||||
// True Heading
|
||||
std::uint16_t trueHeading;
|
||||
in.read(reinterpret_cast<char *>(&trueHeading), sizeof(trueHeading));
|
||||
|
||||
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_simdata::Gate>,
|
||||
std::vector<germanairlinesva_simdata::Runway>>>
|
||||
fromFile(const std::string &file)
|
||||
{
|
||||
std::map<std::string,
|
||||
std::pair<std::vector<germanairlinesva_simdata::Gate>,
|
||||
std::vector<germanairlinesva_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 germanairlinesva_simdata
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "runway.h"
|
||||
namespace germanairlinesva_simdata
|
||||
{
|
||||
Runway::Runway(std::string designator,
|
||||
double latitudeStart,
|
||||
double longitudeStart,
|
||||
double latitudeEnd,
|
||||
double longitudeEnd,
|
||||
double width)
|
||||
{
|
||||
this->designator = std::move(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);
|
||||
|
||||
file = std::vector<std::uint8_t>(
|
||||
1 + this->designator.length() + 1 + sizeof(this->bounds) +
|
||||
sizeof(this->width) + sizeof(this->length) +
|
||||
sizeof(this->trueHeading),
|
||||
0);
|
||||
std::uint8_t *bufPtr = file.data();
|
||||
memset(bufPtr,
|
||||
static_cast<std::uint8_t>(this->designator.length()),
|
||||
sizeof(std::uint8_t));
|
||||
bufPtr++;
|
||||
memcpy(bufPtr, this->designator.c_str(), this->designator.length());
|
||||
bufPtr += this->designator.length() + 1;
|
||||
memcpy(bufPtr, &this->bounds, sizeof(this->bounds));
|
||||
bufPtr += sizeof(this->bounds);
|
||||
memcpy(bufPtr, &this->width, sizeof(this->width));
|
||||
bufPtr += sizeof(this->width);
|
||||
memcpy(bufPtr, &this->length, sizeof(this->length));
|
||||
bufPtr += sizeof(this->length);
|
||||
memcpy(bufPtr, &this->trueHeading, sizeof(this->trueHeading));
|
||||
}
|
||||
|
||||
Runway::Runway(std::string designator,
|
||||
germanairlinesva_geodata::box bounds,
|
||||
std::uint8_t width,
|
||||
std::uint16_t length,
|
||||
std::uint16_t trueHeading)
|
||||
{
|
||||
this->designator = std::move(designator);
|
||||
this->bounds = bounds;
|
||||
this->width = width;
|
||||
this->length = length;
|
||||
this->trueHeading = trueHeading;
|
||||
|
||||
file = std::vector<std::uint8_t>(
|
||||
1 + this->designator.length() + 1 + sizeof(this->bounds) +
|
||||
sizeof(this->width) + sizeof(this->length) +
|
||||
sizeof(this->trueHeading),
|
||||
0);
|
||||
std::uint8_t *bufPtr = file.data();
|
||||
memset(bufPtr,
|
||||
static_cast<std::uint8_t>(this->designator.length()),
|
||||
sizeof(std::uint8_t));
|
||||
bufPtr++;
|
||||
memcpy(bufPtr, this->designator.c_str(), this->designator.length());
|
||||
bufPtr += this->designator.length() + 1;
|
||||
memcpy(bufPtr, &this->bounds, sizeof(this->bounds));
|
||||
bufPtr += sizeof(this->bounds);
|
||||
memcpy(bufPtr, &this->width, sizeof(this->width));
|
||||
bufPtr += sizeof(this->width);
|
||||
memcpy(bufPtr, &this->length, sizeof(this->length));
|
||||
bufPtr += sizeof(this->length);
|
||||
memcpy(bufPtr, &this->trueHeading, sizeof(this->trueHeading));
|
||||
}
|
||||
} // namespace germanairlinesva_simdata
|
||||
@@ -0,0 +1,184 @@
|
||||
#include "simdata.h"
|
||||
namespace germanairlinesva_simdata
|
||||
{
|
||||
int scan(
|
||||
const char *defaultFile,
|
||||
const char *sceneryPack,
|
||||
const char *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::ios::out | std::ios::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.push_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, 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");
|
||||
|
||||
gates->push_back(
|
||||
Gate{gateName, std::stod(fields[1]), std::stod(fields[2]), 40});
|
||||
}
|
||||
|
||||
void makeRunway(std::vector<Runway> *runways, std::vector<std::string> fields)
|
||||
{
|
||||
runways->push_back(Runway{fields[8],
|
||||
std::stod(fields[9]),
|
||||
std::stod(fields[10]),
|
||||
std::stod(fields[18]),
|
||||
std::stod(fields[19]),
|
||||
std::stod(fields[1])});
|
||||
runways->push_back(Runway{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, 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");
|
||||
|
||||
gates->push_back(
|
||||
Gate{gateName, std::stod(fields[1]), std::stod(fields[2]), 40});
|
||||
}
|
||||
} // namespace germanairlinesva_simdata
|
||||
Reference in New Issue
Block a user