#ifndef GERMANAIRLINESVA_FILE_SIMDATA_RUNWAY_H #define GERMANAIRLINESVA_FILE_SIMDATA_RUNWAY_H #include #include #include #include #include #include #include #include #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 true * Threshold center in lat/lon degrees * Width and length in metres * * UINT8 | CHAR[] | BOX | UINT8 | UINT16 | DOUBLE * -------+------------+--------+-------+--------+------- * STRLEN | DESIGNATOR | BOUNDS | WIDTH | LENGTH | TRUHDG */ class Runway { private: std::string designator; struct geodata::box bounds; std::uint8_t width; std::uint16_t length; double trueHeading; public: // From X-Plane inline Runway(std::string designator, double latitudeStart, double longitudeStart, double latitudeEnd, double longitudeEnd, double width) : designator(designator), width(width) { this->length = geodata::distanceEarthD(latitudeStart, longitudeStart, latitudeEnd, longitudeEnd); this->trueHeading = geodata::bearingDD(latitudeStart, longitudeStart, latitudeEnd, longitudeEnd); this->bounds = geodata::calculateBoxDD({latitudeStart, longitudeStart}, {latitudeEnd, longitudeEnd}, this->trueHeading, this->width); }; // From MakeRwys inline Runway(std::string designator, struct geodata::point start, double width, double length, double trueHeading) : designator(designator), width(width), length(length), trueHeading(trueHeading) { geodata::point end = geodata::calculatePointDD(start, trueHeading, length); this->bounds = geodata::calculateBoxDD(start, end, trueHeading, width); }; // From database inline Runway(std::string designator, struct geodata::box bounds, std::uint8_t width, std::uint16_t length, double trueHeading) : designator(designator), bounds(bounds), width(width), length(length), trueHeading(trueHeading){}; inline bool containsPoint(const geodata::point point) const { size_t j = 3; bool c = false; std::vector poly{this->bounds.topLeft, this->bounds.topRight, this->bounds.bottomRight, this->bounds.bottomLeft}; for (size_t i = 0; i < poly.size(); i++) { if ((point.latitude == poly[i].latitude) && (point.longitude == poly[i].longitude)) { // point is a corner return true; } if (((poly[i].longitude > point.longitude) != (poly[j].longitude > point.longitude))) { double slope = (point.latitude - poly[i].latitude) * (poly[j].longitude - poly[i].longitude) - (poly[j].latitude - poly[i].latitude) * (point.longitude - poly[i].longitude); if (slope == 0) { // point is on boundary return true; } if ((slope < 0) != (poly[j].longitude < poly[i].longitude)) { c = !c; } } j = i; } return c; } inline void toFile(std::ofstream &out) const { writeString(out, this->designator); writebounds)>(out, this->bounds); writewidth)>(out, this->width); writelength)>(out, this->length); writetrueHeading)>(out, this->trueHeading); } 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