161 lines
5.7 KiB
C++

#ifndef GERMANAIRLINESVA_FILE_SIMDATA_RUNWAY_H
#define GERMANAIRLINESVA_FILE_SIMDATA_RUNWAY_H
#include <fstream>
#include <iomanip>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#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<geodata::point> 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);
write<decltype(this->bounds)>(out, this->bounds);
write<decltype(this->width)>(out, this->width);
write<decltype(this->length)>(out, this->length);
write<decltype(this->trueHeading)>(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