6 #include <QStringBuilder>
19 using namespace swift::misc::physical_quantities;
20 using namespace swift::misc::math;
22 namespace swift::misc::aviation
25 void CAltitude::registerMetadata()
28 qRegisterMetaType<CAltitude::ReferenceDatum>();
29 qRegisterMetaType<CAltitude::AltitudeType>();
32 const QVector<CAltitude::MetricTuple> &CAltitude::metricTuples()
34 static const QVector<MetricTuple> v = {
35 { 300, 1000 }, { 600, 2000 }, { 900, 3000 }, { 1200, 3900 }, { 1200, 4000 }, { 1500, 4900 },
36 { 1500, 5000 }, { 1800, 5900 }, { 1850, 6000 }, { 2100, 6900 }, { 2150, 7000 }, { 2400, 7900 },
37 { 2450, 8000 }, { 2700, 8900 }, { 2750, 9000 }, { 3000, 9800 }, { 3050, 10000 }, { 3300, 10800 },
38 { 3350, 11000 }, { 3600, 11800 }, { 3650, 12000 }, { 3900, 12800 }, { 3950, 13000 }, { 4200, 13800 },
39 { 4250, 14000 }, { 4500, 14800 }, { 4550, 15000 }, { 4800, 15700 }, { 4900, 16000 }, { 5100, 16700 },
40 { 5200, 17000 }, { 5400, 17700 }, { 5500, 18000 }, { 5700, 18700 }, { 5800, 19000 }, { 6000, 19700 },
41 { 6100, 20000 }, { 6300, 20700 }, { 6400, 21000 }, { 6600, 21700 }, { 6700, 22000 }, { 6900, 22600 },
42 { 7000, 23000 }, { 7200, 23600 }, { 7300, 24000 }, { 7500, 24600 }, { 7600, 25000 }, { 7800, 25600 },
43 { 7900, 26000 }, { 8100, 26600 }, { 8250, 27000 }, { 8400, 27600 }, { 8550, 28000 }, { 8600, 28200 },
44 { 8850, 29000 }, { 8900, 29100 }, { 9100, 29900 }, { 9150, 30000 }, { 9200, 30100 }, { 9450, 31000 },
45 { 9500, 31100 }, { 9600, 31500 }, { 9750, 32000 }, { 9800, 32100 }, { 10050, 33000 }, { 10100, 33100 },
46 { 10350, 34000 }, { 10400, 34100 }, { 10600, 34800 }, { 10650, 35000 }, { 10700, 35100 }, { 10950, 36000 },
47 { 11000, 36100 }, { 11100, 36400 }, { 11300, 37000 }, { 11300, 37100 }, { 11600, 38000 }, { 11600, 38100 },
48 { 11900, 39000 }, { 11900, 39100 }, { 12100, 39700 }, { 12200, 40000 }, { 12200, 40100 }, { 12500, 41000 },
49 { 13100, 43000 }, { 13700, 44900 }, { 13700, 45000 }, { 14100, 46300 }, { 14300, 46900 }, { 14350, 47000 },
50 { 14900, 48900 }, { 14950, 49000 }, { 15100, 49500 }, { 15550, 51000 },
73 if (newUnit.
isNull() || this->getUnit().isNull() || this->getUnit() == newUnit) {
return *
this; }
74 CLength::switchUnit(newUnit);
80 if (newUnit.
isNull() || this->getUnit().isNull() || this->getUnit() == newUnit) {
return *
this; }
88 static const QString n(
"null");
89 if (this->
isNull()) {
return n; }
93 const int fl = qRound(this->CLength::value(CLengthUnit::ft()) / 100.0);
94 return QStringLiteral(
"FL%1").arg(fl);
96 else {
return this->CLength::valueRoundedWithUnit(1, i18n) % (this->
isMeanSeaLevel() ? u
" MSL" : u
" AGL"); }
102 return CLength::comparePropertyByIndex(index, compareValue);
122 if (this->
isNull()) {
return; }
124 const double deltaPressureV = deltaPressure.
value(CPressureUnit::mbar());
125 const double deltaAltitudeV = deltaPressureV * 30.0;
126 CLength deltaAltitude(deltaAltitudeV, CLengthUnit::ft());
127 *
this += deltaAltitude;
147 QString v =
value.trimmed();
150 if (v.contains(
"FL", Qt::CaseInsensitive) || v.startsWith(
"F"))
154 const int dv = v.toInt(&ok) * 100;
161 if (v.contains(
"ALT", Qt::CaseInsensitive) || v.startsWith(
"A"))
165 const int dv = v.toInt(&ok) * 100;
173 if (v.contains(
"MSL", Qt::CaseInsensitive))
175 v = v.replace(
"MSL",
"", Qt::CaseInsensitive).trimmed();
178 else if (v.contains(
"AGL"))
180 v = v.replace(
"AGL",
"", Qt::CaseInsensitive).trimmed();
184 const CLength l = CPqString::parse<CLength>(v, mode);
190 QString v(
value.trimmed());
191 if (v.startsWith(
"VFR", Qt::CaseInsensitive))
217 bool beforeDigit =
true;
219 for (
int i = 0; i < v.length(); i++)
221 const QChar c = v[i];
225 numericPart.push_back(c);
228 v[i] = beforeDigit ? c.toUpper() : c.toLower();
231 if (numericPart.isEmpty())
238 if (v.startsWith(
"F", Qt::CaseInsensitive))
240 this->
setUnit(CLengthUnit::ft());
244 else if (v.startsWith(
"S", Qt::CaseInsensitive))
246 this->
setUnit(CLengthUnit::m());
250 else if (v.startsWith(
"A", Qt::CaseInsensitive))
252 this->
setUnit(CLengthUnit::ft());
256 else if (v.startsWith(
"M", Qt::CaseInsensitive))
258 this->
setUnit(CLengthUnit::m());
262 else if (v.endsWith(CLengthUnit::m().getSymbol()))
264 this->
setUnit(CLengthUnit::m());
268 else if (v.endsWith(CLengthUnit::ft().getSymbol()))
270 this->
setUnit(CLengthUnit::ft());
286 if (!valid) { this->
setNull(); }
302 if (!(this->
getUnit() == CLengthUnit::m() || this->
getUnit() == CLengthUnit::ft()))
323 if (this->
getUnit() == CLengthUnit::ft())
326 if (flInt < 10 || flInt >= 1000)
331 if (!CMathUtils::epsilonZero(fmod(flInt, 5)))
342 if (this->
isNull()) {
return {}; }
345 if (this->
getUnit() == CLengthUnit::m())
348 return QStringLiteral(
"S%1").arg(m, 4, 10, QChar(
'0'));
351 return QStringLiteral(
"FL%1").arg(ft, 3, 10, QChar(
'0'));
354 if (this->
getUnit() == CLengthUnit::m())
357 return QStringLiteral(
"M%1").arg(m, 4, 10, QChar(
'0'));
360 return QStringLiteral(
"A%1").arg(ft, 3, 10, QChar(
'0'));
376 thread_local
const QRegularExpression re(
377 "([Ff][Ll]?\\d{2,3})|([Ss]\\d{2,4})|([Aa]\\d{2,3})|([Mm]\\d{2,4})|(\\d{3,5}(ft|m))");
385 static const QString e(
386 "FL085, F85 flight level in hecto feets%1S0150 metric level in tens of meters%1A055 altitude in hundreds "
387 "of feet%012000ft altitude in ft%1M0610 altitude in tens of meters%016100m altitude in meters");
388 return e.arg(separator);
393 static const QString e(
"FL085, F85, S0150, A055, 1200ft, M0610, 6100m");
406 return CLength::compare(*
this, otherAltitude);
413 const double ft = a.
value(CLengthUnit::ft()) / 100.0;
414 const int ftR = roundDown ?
static_cast<int>(floor(ft)) * 100 : qRound(ft) * 100;
424 if (std::get<1>(m) == feet)
return std::get<0>(m);
434 if (std::get<0>(m) == metric)
return std::get<1>(m);
450 static const CPressure standardPressure(CPhysicalQuantitiesConstants::ISASeaLevelPressure());
451 return standardPressure;
IconIndex
Index for each icon, allows to send them via DBus, efficiently store them, etc.
Non-owning reference to a CPropertyIndex with a subset of its features.
bool isMyself() const
Myself index, used with nesting.
void push_back(const T &value)
Appends an element at the end of the sequence.
Streamable status message, e.g.
Status messages, e.g. from Core -> GUI.
Altitude as used in aviation, can be AGL or MSL altitude.
QString asFpVatsimAltitudeString() const
As simple VATSIM string, only FLxxx or altitude as ft.
CAltitude switchedUnit(const physical_quantities::CLengthUnit &newUnit) const
Value in switched unit.
void parseFromString(const QString &value)
Parse value from string.
bool isValidFpAltitude(CStatusMessageList *msgs=nullptr) const
Is this a valid FP altitude.
static physical_quantities::CLengthUnit defaultUnit()
Default unit for calculations.
static QString fpAltitudeExamples()
Examples of FP altitude strings.
static int findMetricAltitude(int feet)
Search the corresponding feet <-> metric / metric <-> feet.
bool toFlightLevel()
MSL to flightlevel.
int comparePropertyByIndex(CPropertyIndexRef index, const CAltitude &compareValue) const
Set property by index.
QString asFpICAOAltitudeString() const
Altitude string (official version)
bool parseFromFpAltitudeString(const QString &value, CStatusMessageList *msgs=nullptr)
Parse from FP altitude string.
bool isMeanSeaLevel() const
MSL Mean sea level?
CAltitude withOffset(const CLength &offset) const
Altitude with offset.
static int findAltitudeForMetricAltitude(int metric)
Search the corresponding feet <-> metric / metric <-> feet.
QString convertToQString(bool i18n=false) const
Cast as QString.
bool isFlightLevel() const
Flight level?
CAltitude & switchUnit(const physical_quantities::CLengthUnit &newUnit)
Value in switched unit.
static QString fpAltitudeInfo(const QString &separator=", ")
Info for FP altitude strings.
int compare(const CAltitude &otherAltitude) const
Return negative, zero, or positive if a is less than, equal to, or greater than b.
CAltitude()
Default constructor: 0m Altitude MSL.
@ PressureAltitude
Altitude above the standard datum plane.
void convertToPressureAltitude(const physical_quantities::CPressure &seaLevelPressure)
Converts this to pressure altitude. Requires the current barometric pressure at MSL.
CAltitude roundedToNearest100ft(bool roundDown) const
Round to the nearest 100ft, like needed for China and Russia.
void addOffset(const CLength &offset)
Add offset value.
ReferenceDatum
Enum type to distinguish between MSL and AGL.
@ FlightLevel
Flight level.
static const QRegularExpression & fpAltitudeRegExp()
Checking FP altitude strings like "A20", "FL100".
static const CAltitude & null()
Null altitude (MSL)
std::tuple< int, int > MetricTuple
Metric tuple.
swift::misc::CIcons::IconIndex toIcon() const
As icon, not implemented by all classes.
ReferenceDatum getReferenceDatum() const
Get reference datum (MSL or AGL)
CAltitude toPressureAltitude(const physical_quantities::CPressure &seaLevelPressure) const
Returns the altitude converted to pressure altitude. Requires the current barometric pressure at MSL.
static const physical_quantities::CPressure & standardISASeaLevelPressure()
Standard pressure 1013.25mbar/hPa.
bool toMeanSeaLevel()
Flightlevel to MSL.
Physical unit length (length)
Specialized class for distance units (meter, foot, nautical miles).
bool isNull() const
Is unit null?
double value() const
Value in current unit.
bool isNegativeWithEpsilonConsidered() const
Value <= 0 epsilon considered.
void setValueSameUnit(double value)
Change value without changing unit.
PQ switchedUnit(const MU &newUnit) const
Return copy with switched unit.
const CLengthUnit & getUnit() const
Unit.
bool isInteger() const
Is value an integer.
bool isNull() const
Is quantity null?
double value(MU unit) const
Value in given unit.
QString valueIntegerAsString(MU unit) const
As integer value.
void setUnit(const CLengthUnit &unit)
Simply set unit, do no calclulate conversion.
int valueInteger() const
As integer value in current unit.
bool isZeroEpsilonConsidered() const
Quantity value <= epsilon.
SeparatorMode
Number separators / group separators.
QString char09OnlyString(const QString &string)
String only with 0-9.