mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-16 18:35:35 +08:00
refs #707, refactoring geo interfaces
* added compare functions (also to ATC list) * renamed to relative position, e.g. station.setRelativeDistance * delegate set/get/compare to correct interface
This commit is contained in:
@@ -66,13 +66,9 @@ namespace BlackMisc
|
||||
return this->m_position.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexElevation:
|
||||
return this->getElevation().propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexBearing:
|
||||
return this->m_bearingToOwnAircraft.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexDistanceToOwnAircraft:
|
||||
return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved());
|
||||
default:
|
||||
return (ICoordinateGeodetic::canHandleIndex(index)) ?
|
||||
ICoordinateGeodetic::propertyByIndex(index) :
|
||||
return (ICoordinateWithRelativePosition::canHandleIndex(index)) ?
|
||||
ICoordinateWithRelativePosition::propertyByIndex(index) :
|
||||
CValueObject::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
@@ -92,14 +88,15 @@ namespace BlackMisc
|
||||
case IndexPosition:
|
||||
this->m_position.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexBearing:
|
||||
this->m_bearingToOwnAircraft.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexDistanceToOwnAircraft:
|
||||
this->m_distanceToOwnAircraft.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
default:
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
ICoordinateWithRelativePosition::setPropertyByIndex(index, variant);
|
||||
}
|
||||
else
|
||||
{
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -114,17 +111,15 @@ namespace BlackMisc
|
||||
return this->m_icao.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getIcao());
|
||||
case IndexDescriptiveName:
|
||||
return this->m_descriptiveName.compare(compareValue.getDescriptiveName(), Qt::CaseInsensitive);
|
||||
case IndexBearing:
|
||||
return this->m_bearingToOwnAircraft.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getBearingToOwnAircraft());
|
||||
case IndexPosition:
|
||||
case IndexDistanceToOwnAircraft:
|
||||
return this->m_distanceToOwnAircraft.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getDistanceToOwnAircraft());
|
||||
default:
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
return ICoordinateWithRelativePosition::comparePropertyByIndex(index, compareValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Compare failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -42,9 +42,7 @@ namespace BlackMisc
|
||||
IndexIcao = BlackMisc::CPropertyIndex::GlobalIndexCAirport,
|
||||
IndexDescriptiveName,
|
||||
IndexPosition,
|
||||
IndexElevation,
|
||||
IndexDistanceToOwnAircraft,
|
||||
IndexBearing
|
||||
IndexElevation
|
||||
};
|
||||
|
||||
//! Default constructor.
|
||||
@@ -119,7 +117,7 @@ namespace BlackMisc
|
||||
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
|
||||
void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const CVariant &variant);
|
||||
|
||||
//! Compare for index
|
||||
//! Compare by index
|
||||
int comparePropertyByIndex(const CPropertyIndex &index, const CAirport &compareValue) const;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
@@ -135,8 +133,8 @@ namespace BlackMisc
|
||||
BLACK_METAMEMBER(icao),
|
||||
BLACK_METAMEMBER(descriptiveName),
|
||||
BLACK_METAMEMBER(position),
|
||||
BLACK_METAMEMBER(distanceToOwnAircraft),
|
||||
BLACK_METAMEMBER(bearingToOwnAircraft)
|
||||
BLACK_METAMEMBER(relativeDistance),
|
||||
BLACK_METAMEMBER(relativeBearing)
|
||||
);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
#include "blackmisc/pq/units.h"
|
||||
#include "blackmisc/propertyindex.h"
|
||||
#include "blackmisc/variant.h"
|
||||
#include "blackmisc/comparefunctions.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QtGlobal>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
using namespace BlackMisc::Network;
|
||||
@@ -133,12 +135,12 @@ namespace BlackMisc
|
||||
s.append(this->m_range.toQString(i18n));
|
||||
|
||||
// distance to plane
|
||||
if (this->m_distanceToOwnAircraft.isPositiveWithEpsilonConsidered())
|
||||
if (this->m_relativeDistance.isPositiveWithEpsilonConsidered())
|
||||
{
|
||||
s.append(' ');
|
||||
i18n ? s.append(QCoreApplication::translate("Aviation", "distance")) : s.append("distance");
|
||||
s.append(' ');
|
||||
s.append(this->m_distanceToOwnAircraft.toQString(i18n));
|
||||
s.append(this->m_relativeDistance.toQString(i18n));
|
||||
}
|
||||
|
||||
// from / to
|
||||
@@ -260,22 +262,22 @@ namespace BlackMisc
|
||||
|
||||
// both ways
|
||||
this->syncronizeControllerData(bookedStation);
|
||||
if (this->hasValidDistance())
|
||||
if (this->hasValidRelativeDistance())
|
||||
{
|
||||
bookedStation.setDistanceToOwnAircraft(this->getDistanceToOwnAircraft());
|
||||
bookedStation.setBearingToOwnAircraft(this->getBearingToOwnAircraft());
|
||||
bookedStation.setRelativeDistance(this->getRelativeDistance());
|
||||
bookedStation.setRelativeBearing(this->getRelativeBearing());
|
||||
}
|
||||
else if (bookedStation.hasValidDistance())
|
||||
else if (bookedStation.hasValidRelativeDistance())
|
||||
{
|
||||
this->setDistanceToOwnAircraft(bookedStation.getDistanceToOwnAircraft());
|
||||
this->setBearingToOwnAircraft(bookedStation.getBearingToOwnAircraft());
|
||||
this->setRelativeDistance(bookedStation.getRelativeDistance());
|
||||
this->setRelativeBearing(bookedStation.getRelativeBearing());
|
||||
}
|
||||
}
|
||||
|
||||
bool CAtcStation::isInRange() const
|
||||
{
|
||||
if (m_range.isNull() || !hasValidDistance()) { return false; }
|
||||
return (this->getDistanceToOwnAircraft() <= m_range);
|
||||
if (m_range.isNull() || !hasValidRelativeDistance()) { return false; }
|
||||
return (this->getRelativeDistance() <= m_range);
|
||||
}
|
||||
|
||||
bool CAtcStation::hasValidBookingTimes() const
|
||||
@@ -373,8 +375,6 @@ namespace BlackMisc
|
||||
return CVariant::from(this->m_isOnline);
|
||||
case IndexLatitude:
|
||||
return this->latitude().propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexDistanceToOwnAircraft:
|
||||
return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexLongitude:
|
||||
return this->longitude().propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexPosition:
|
||||
@@ -390,8 +390,9 @@ namespace BlackMisc
|
||||
case IndexVoiceRoom:
|
||||
return this->m_voiceRoom.propertyByIndex(index.copyFrontRemoved());
|
||||
default:
|
||||
if (ICoordinateGeodetic::canHandleIndex(index)) { return ICoordinateGeodetic::propertyByIndex(index); }
|
||||
return CValueObject::propertyByIndex(index);
|
||||
return (ICoordinateWithRelativePosition::canHandleIndex(index)) ?
|
||||
ICoordinateWithRelativePosition::propertyByIndex(index) :
|
||||
CValueObject::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,9 +426,6 @@ namespace BlackMisc
|
||||
case IndexRange:
|
||||
this->m_range.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexDistanceToOwnAircraft:
|
||||
this->m_distanceToOwnAircraft.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexAtis:
|
||||
this->m_atis.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
@@ -438,9 +436,61 @@ namespace BlackMisc
|
||||
this->m_voiceRoom.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
default:
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
ICoordinateWithRelativePosition::setPropertyByIndex(index, variant);
|
||||
}
|
||||
else
|
||||
{
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int CAtcStation::comparePropertyByIndex(const CPropertyIndex &index, const CAtcStation &compareValue) const
|
||||
{
|
||||
if (index.isMyself()) { return this->getCallsign().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCallsign()); }
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexBookedFrom:
|
||||
return Compare::compare(this->getBookedFromUtc(), compareValue.getBookedFromUtc());
|
||||
case IndexBookedUntil:
|
||||
return Compare::compare(this->getBookedUntilUtc(), compareValue.getBookedUntilUtc());
|
||||
case IndexCallsign:
|
||||
return this->m_callsign.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCallsign());
|
||||
case IndexController:
|
||||
return this->m_controller.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getController());
|
||||
case IndexFrequency:
|
||||
return this->m_frequency.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getFrequency());
|
||||
case IndexIsOnline:
|
||||
return Compare::compare(this->isOnline(), compareValue.isOnline());
|
||||
case IndexLatitude:
|
||||
return this->latitude().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.latitude());
|
||||
case IndexLongitude:
|
||||
return this->longitude().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.longitude());
|
||||
case IndexPosition:
|
||||
return this->m_position.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getPosition());
|
||||
case IndexRange:
|
||||
return this->m_range.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getRange());
|
||||
case IndexIsInRange:
|
||||
return Compare::compare(this->isInRange(), compareValue.isInRange());
|
||||
case IndexAtis:
|
||||
return this->m_atis.getMessage().compare(compareValue.getAtis().getMessage());
|
||||
case IndexMetar:
|
||||
return this->m_metar.getMessage().compare(compareValue.getMetar().getMessage());
|
||||
case IndexVoiceRoom:
|
||||
return this->getVoiceRoom().getVoiceRoomUrl().compare(compareValue.getVoiceRoom().getVoiceRoomUrl());
|
||||
default:
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
return ICoordinateWithRelativePosition::comparePropertyByIndex(index, compareValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Compare failed");
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace BlackMisc
|
||||
IndexPosition,
|
||||
IndexRange,
|
||||
IndexIsInRange,
|
||||
IndexDistanceToOwnAircraft,
|
||||
IndexIsOnline,
|
||||
IndexBookedFrom,
|
||||
IndexBookedUntil,
|
||||
@@ -148,7 +147,6 @@ namespace BlackMisc
|
||||
//! Updates two stations (normally a booked and online ATC station) with complementary data
|
||||
void syncronizeControllerData(CAtcStation &otherStation);
|
||||
|
||||
|
||||
//! Syncronize station data
|
||||
//! Updates the two stations (a booked and online ATC station) with complementary data
|
||||
//! \pre this object is the online station, the passed station the booked station
|
||||
@@ -253,6 +251,9 @@ namespace BlackMisc
|
||||
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
|
||||
void setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant);
|
||||
|
||||
//! Compare by index
|
||||
int comparePropertyByIndex(const CPropertyIndex &index, const CAtcStation &compareValue) const;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const;
|
||||
|
||||
@@ -282,8 +283,8 @@ namespace BlackMisc
|
||||
BLACK_METAMEMBER(bookedUntilUtc),
|
||||
BLACK_METAMEMBER(metar),
|
||||
BLACK_METAMEMBER(voiceRoom),
|
||||
BLACK_METAMEMBER(distanceToOwnAircraft),
|
||||
BLACK_METAMEMBER(bearingToOwnAircraft)
|
||||
BLACK_METAMEMBER(relativeDistance),
|
||||
BLACK_METAMEMBER(relativeBearing)
|
||||
);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -38,5 +38,9 @@ namespace BlackMisc
|
||||
return a < b ? -10 : 10;
|
||||
}
|
||||
|
||||
int compare(const QDateTime &a, const QDateTime &b)
|
||||
{
|
||||
return Compare::compare(a.toMSecsSinceEpoch(), b.toMSecsSinceEpoch());
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define BLACKMISC_COMPAREFUNCTIONS_H
|
||||
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace BlackMisc
|
||||
@@ -29,8 +29,11 @@ namespace BlackMisc
|
||||
//! Compare qint64
|
||||
BLACKMISC_EXPORT int compare(qint64 a, qint64 b);
|
||||
|
||||
//! Compare qint64
|
||||
//! Compare double
|
||||
BLACKMISC_EXPORT int compare(double a, double b);
|
||||
|
||||
//! Compare double
|
||||
BLACKMISC_EXPORT int compare(const QDateTime &a, const QDateTime &b);
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
QString CCoordinateGeodetic::convertToQString(bool i18n) const
|
||||
{
|
||||
QString s = "Geodetic: {%1, %2, %3}";
|
||||
@@ -74,7 +73,7 @@ namespace BlackMisc
|
||||
return Geo::calculateGreatCircleDistance((*this), otherCoordinate);
|
||||
}
|
||||
|
||||
CAngle ICoordinateGeodetic::bearing(const ICoordinateGeodetic &otherCoordinate) const
|
||||
CAngle ICoordinateGeodetic::calculateBearing(const ICoordinateGeodetic &otherCoordinate) const
|
||||
{
|
||||
return Geo::calculateBearing((*this), otherCoordinate);
|
||||
}
|
||||
@@ -112,10 +111,39 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
const QString m = QString("no property, index ").append(index.toQString());
|
||||
Q_ASSERT_X(false, "ICoordinateGeodetic", m.toLocal8Bit().constData());
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, m.toLocal8Bit().constData());
|
||||
return CVariant::fromValue(m);
|
||||
}
|
||||
|
||||
int ICoordinateGeodetic::comparePropertyByIndex(const CPropertyIndex &index, const ICoordinateGeodetic &compareValue) const
|
||||
{
|
||||
if (!index.isMyself())
|
||||
{
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexLatitude:
|
||||
return this->latitude().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.latitude());
|
||||
case IndexLongitude:
|
||||
return this->longitude().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.longitude());
|
||||
case IndexLatitudeAsString:
|
||||
return this->latitudeAsString().compare(compareValue.latitudeAsString());
|
||||
case IndexLongitudeAsString:
|
||||
return this->longitudeAsString().compare(compareValue.longitudeAsString());
|
||||
case IndexGeodeticHeight:
|
||||
return this->geodeticHeight().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.geodeticHeight());
|
||||
case IndexGeodeticHeightAsString:
|
||||
return this->geodeticHeightAsString().compare(compareValue.geodeticHeightAsString());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const QString m = QString("no property, index ").append(index.toQString());
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, m.toLocal8Bit().constData());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CVariant CCoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
|
||||
{
|
||||
if (index.isMyself()) { return CVariant::from(*this); }
|
||||
@@ -217,23 +245,89 @@ namespace BlackMisc
|
||||
return *this;
|
||||
}
|
||||
|
||||
CLength ICoordinateWithRelativePosition::calculcateDistanceToOwnAircraft(const ICoordinateGeodetic &position, bool updateValues)
|
||||
CLength ICoordinateWithRelativePosition::calculcateAndUpdateRelativeDistance(const ICoordinateGeodetic &position)
|
||||
{
|
||||
if (!updateValues) { return Geo::calculateGreatCircleDistance(*this, position); }
|
||||
this->m_distanceToOwnAircraft = Geo::calculateGreatCircleDistance(*this, position);
|
||||
return this->m_distanceToOwnAircraft;
|
||||
this->m_relativeDistance = Geo::calculateGreatCircleDistance(*this, position);
|
||||
return this->m_relativeDistance;
|
||||
}
|
||||
|
||||
CLength ICoordinateWithRelativePosition::calculcateDistanceAndBearingToOwnAircraft(const ICoordinateGeodetic &position, bool updateValues)
|
||||
CLength ICoordinateWithRelativePosition::calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position)
|
||||
{
|
||||
if (!updateValues) { return Geo::calculateGreatCircleDistance(*this, position); }
|
||||
this->m_distanceToOwnAircraft = Geo::calculateGreatCircleDistance(*this, position);
|
||||
this->m_bearingToOwnAircraft = Geo::calculateBearing(*this, position);
|
||||
return this->m_distanceToOwnAircraft;
|
||||
this->m_relativeDistance = Geo::calculateGreatCircleDistance(*this, position);
|
||||
this->m_relativeBearing = Geo::calculateBearing(*this, position);
|
||||
return this->m_relativeDistance;
|
||||
}
|
||||
|
||||
CVariant ICoordinateWithRelativePosition::propertyByIndex(const CPropertyIndex &index) const
|
||||
{
|
||||
if (ICoordinateGeodetic::canHandleIndex(index)) { return ICoordinateGeodetic::propertyByIndex(index); }
|
||||
if (!index.isMyself())
|
||||
{
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexRelativeBearing:
|
||||
return this->getRelativeBearing().propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexRelativeDistance:
|
||||
return this->getRelativeDistance().propertyByIndex(index.copyFrontRemoved());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
const QString m = QString("no property, index ").append(index.toQString());
|
||||
Q_ASSERT_X(false, "ICoordinateWithRelativePosition", m.toLocal8Bit().constData());
|
||||
return CVariant::fromValue(m);
|
||||
}
|
||||
|
||||
void ICoordinateWithRelativePosition::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant)
|
||||
{
|
||||
if (!index.isMyself())
|
||||
{
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexRelativeBearing:
|
||||
this->m_relativeBearing.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexRelativeDistance:
|
||||
this->m_relativeDistance.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
default:
|
||||
const QString m = QString("no property, index ").append(index.toQString());
|
||||
Q_ASSERT_X(false, "ICoordinateWithRelativePosition", m.toLocal8Bit().constData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ICoordinateWithRelativePosition::comparePropertyByIndex(const CPropertyIndex &index, const ICoordinateWithRelativePosition &compareValue) const
|
||||
{
|
||||
if (ICoordinateGeodetic::canHandleIndex(index)) { return ICoordinateGeodetic::comparePropertyByIndex(index, compareValue); }
|
||||
if (!index.isMyself())
|
||||
{
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexRelativeBearing:
|
||||
return this->m_relativeBearing.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getRelativeBearing());
|
||||
case IndexRelativeDistance:
|
||||
return this->m_relativeDistance.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getRelativeDistance());
|
||||
default:
|
||||
const QString m = QString("no property, index ").append(index.toQString());
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, m.toLocal8Bit().constData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ICoordinateWithRelativePosition::ICoordinateWithRelativePosition()
|
||||
{ }
|
||||
|
||||
bool ICoordinateWithRelativePosition::canHandleIndex(const CPropertyIndex &index)
|
||||
{
|
||||
int i = index.frontCasted<int>();
|
||||
return (i >= static_cast<int>(IndexRelativeDistance)) && (i <= static_cast<int>(IndexRelativeBearing));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
|
||||
//! Geodetic coordinate
|
||||
//! \sa http://www.esri.com/news/arcuser/0703/geoid1of3.html
|
||||
//! \sa http://http://www.gmat.unsw.edu.au/snap/gps/clynch_pdfs/coordcvt.pdf (page 5)
|
||||
@@ -76,9 +75,6 @@ namespace BlackMisc
|
||||
//! Normal vector with double precision
|
||||
virtual std::array<double, 3> normalVectorDouble() const = 0;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
|
||||
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
|
||||
|
||||
//! Latitude as string
|
||||
QString latitudeAsString() const { return this->latitude().toQString(true); }
|
||||
|
||||
@@ -92,7 +88,13 @@ namespace BlackMisc
|
||||
BlackMisc::PhysicalQuantities::CLength calculateGreatCircleDistance(const ICoordinateGeodetic &otherCoordinate) const;
|
||||
|
||||
//! Initial bearing
|
||||
BlackMisc::PhysicalQuantities::CAngle bearing(const ICoordinateGeodetic &otherCoordinate) const;
|
||||
BlackMisc::PhysicalQuantities::CAngle calculateBearing(const ICoordinateGeodetic &otherCoordinate) const;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
|
||||
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
|
||||
|
||||
//! Compare by index
|
||||
int comparePropertyByIndex(const CPropertyIndex &index, const ICoordinateGeodetic &compareValue) const;
|
||||
|
||||
protected:
|
||||
//! Can given index be handled?
|
||||
@@ -111,48 +113,64 @@ namespace BlackMisc
|
||||
//! Euclidean distance squared between normal vectors, use for more efficient sorting by distance
|
||||
BLACKMISC_EXPORT double calculateEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate1, const ICoordinateGeodetic &coordinate2);
|
||||
|
||||
//! Interface (actually more an abstract class) of coordinate and
|
||||
//! relative position to own aircraft
|
||||
//! Interface (actually more an abstract class) of coordinates and relative position to something (normally own aircraft)
|
||||
class BLACKMISC_EXPORT ICoordinateWithRelativePosition : public ICoordinateGeodetic
|
||||
{
|
||||
public:
|
||||
//! Get the distance to own plane
|
||||
const BlackMisc::PhysicalQuantities::CLength &getDistanceToOwnAircraft() const { return m_distanceToOwnAircraft; }
|
||||
//! Properties by index
|
||||
enum ColumnIndex
|
||||
{
|
||||
IndexRelativeDistance = BlackMisc::CPropertyIndex::GlobalIndexICoordinateWithRelativePosition,
|
||||
IndexRelativeBearing
|
||||
};
|
||||
|
||||
//! Set distance to own plane
|
||||
void setDistanceToOwnAircraft(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToOwnAircraft = distance; }
|
||||
//! Get the distance
|
||||
const BlackMisc::PhysicalQuantities::CLength &getRelativeDistance() const { return m_relativeDistance; }
|
||||
|
||||
//! Get the bearing to own plane
|
||||
const BlackMisc::PhysicalQuantities::CAngle &getBearingToOwnAircraft() const { return m_bearingToOwnAircraft; }
|
||||
//! Set relative distance
|
||||
void setRelativeDistance(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_relativeDistance = distance; }
|
||||
|
||||
//! Get the relative bearing
|
||||
const BlackMisc::PhysicalQuantities::CAngle &getRelativeBearing() const { return m_relativeBearing; }
|
||||
|
||||
//! Set bearing to own plane
|
||||
void setBearingToOwnAircraft(const BlackMisc::PhysicalQuantities::CAngle &angle) { this->m_bearingToOwnAircraft = angle; }
|
||||
void setRelativeBearing(const BlackMisc::PhysicalQuantities::CAngle &angle) { this->m_relativeBearing = angle; }
|
||||
|
||||
//! Valid distance?
|
||||
bool hasValidDistance() const { return !this->m_distanceToOwnAircraft.isNull();}
|
||||
bool hasValidRelativeDistance() const { return !this->m_relativeDistance.isNull();}
|
||||
|
||||
//! Valid bearing?
|
||||
bool hasValidBearing() const { return !this->m_bearingToOwnAircraft.isNull();}
|
||||
bool hasValidRelativeBearing() const { return !this->m_relativeBearing.isNull();}
|
||||
|
||||
//! Calculcate distance, set it, and return distance
|
||||
BlackMisc::PhysicalQuantities::CLength calculcateDistanceToOwnAircraft(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues = true);
|
||||
BlackMisc::PhysicalQuantities::CLength calculcateAndUpdateRelativeDistance(const BlackMisc::Geo::ICoordinateGeodetic &position);
|
||||
|
||||
//! Calculcate distance and bearing to plane, set it, and return distance
|
||||
BlackMisc::PhysicalQuantities::CLength calculcateDistanceAndBearingToOwnAircraft(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues = true);
|
||||
BlackMisc::PhysicalQuantities::CLength calculcateAndUpdateRelativeDistanceAndBearing(const BlackMisc::Geo::ICoordinateGeodetic &position);
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
|
||||
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
|
||||
void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const CVariant &variant);
|
||||
|
||||
//! Compare by index
|
||||
int comparePropertyByIndex(const CPropertyIndex &index, const ICoordinateWithRelativePosition &compareValue) const;
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
ICoordinateWithRelativePosition();
|
||||
|
||||
BlackMisc::PhysicalQuantities::CAngle m_bearingToOwnAircraft {0.0, BlackMisc::PhysicalQuantities::CAngleUnit::nullUnit()}; //!< temporary stored value
|
||||
BlackMisc::PhysicalQuantities::CLength m_distanceToOwnAircraft {0.0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit()}; //!< temporary stored value
|
||||
};
|
||||
//! Can given index be handled?
|
||||
static bool canHandleIndex(const BlackMisc::CPropertyIndex &index);
|
||||
|
||||
BlackMisc::PhysicalQuantities::CAngle m_relativeBearing {0.0, BlackMisc::PhysicalQuantities::CAngleUnit::nullUnit()}; //!< temporary stored value
|
||||
BlackMisc::PhysicalQuantities::CLength m_relativeDistance {0.0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit()}; //!< temporary stored value
|
||||
};
|
||||
|
||||
//! Geodetic coordinate
|
||||
class BLACKMISC_EXPORT CCoordinateGeodetic : public CValueObject<CCoordinateGeodetic>, public ICoordinateGeodetic
|
||||
{
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
CCoordinateGeodetic() :
|
||||
@@ -166,7 +184,7 @@ namespace BlackMisc
|
||||
|
||||
//! Constructor by values
|
||||
CCoordinateGeodetic(double latitudeDegrees, double longitudeDegrees, double heightMeters) :
|
||||
CCoordinateGeodetic({ latitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { longitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { heightMeters, BlackMisc::PhysicalQuantities::CLengthUnit::m() }) {}
|
||||
CCoordinateGeodetic( { latitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { longitudeDegrees, BlackMisc::PhysicalQuantities::CAngleUnit::deg() }, { heightMeters, BlackMisc::PhysicalQuantities::CLengthUnit::m() }) {}
|
||||
|
||||
//! \copydoc ICoordinateGeodetic::latitude
|
||||
virtual CLatitude latitude() const override;
|
||||
@@ -230,7 +248,6 @@ namespace BlackMisc
|
||||
BLACK_METAMEMBER(geodeticHeight)
|
||||
);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -63,11 +63,11 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
void IGeoObjectWithRelativePositionList<OBJ, CONTAINER>::calculcateDistanceAndBearingToPosition(const ICoordinateGeodetic &position)
|
||||
void IGeoObjectWithRelativePositionList<OBJ, CONTAINER>::calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position)
|
||||
{
|
||||
for (OBJ &geoObj : this->container())
|
||||
{
|
||||
geoObj.calculcateDistanceAndBearingToOwnAircraft(position);
|
||||
geoObj.calculcateAndUpdateRelativeDistanceAndBearing(position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,9 @@ namespace BlackMisc
|
||||
{
|
||||
this->container().removeIf([ & ](OBJ & geoObj)
|
||||
{
|
||||
return geoObj.calculcateDistanceAndBearingToOwnAircraft(position, updateValues) > maxDistance;
|
||||
return updateValues ?
|
||||
geoObj.calculcateAndUpdateRelativeDistanceAndBearing(position) > maxDistance :
|
||||
geoObj.calculateGreatCircleDistance(position) > maxDistance;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -85,21 +87,21 @@ namespace BlackMisc
|
||||
{
|
||||
if (updateValues)
|
||||
{
|
||||
this->calculcateDistanceAndBearingToPosition(position);
|
||||
this->calculcateAndUpdateRelativeDistanceAndBearing(position);
|
||||
}
|
||||
this->container().sort([ & ](const OBJ & a, const OBJ & b) { return a.getDistanceToOwnAircraft() < b.getDistanceToOwnAircraft(); });
|
||||
this->container().sort([ & ](const OBJ & a, const OBJ & b) { return a.getRelativeDistance() < b.getRelativeDistance(); });
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
void IGeoObjectWithRelativePositionList<OBJ, CONTAINER>::sortByDistanceToOwnAircraft()
|
||||
{
|
||||
this->container().sort([ & ](const OBJ & a, const OBJ & b) { return a.getDistanceToOwnAircraft() < b.getDistanceToOwnAircraft(); });
|
||||
this->container().sort([ & ](const OBJ & a, const OBJ & b) { return a.getRelativeDistance() < b.getRelativeDistance(); });
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
void IGeoObjectWithRelativePositionList<OBJ, CONTAINER>::partiallySortByDistanceToOwnAircraft(int number)
|
||||
{
|
||||
this->container().partiallySort(number, [ & ](const OBJ & a, const OBJ & b) { return a.getDistanceToOwnAircraft() < b.getDistanceToOwnAircraft(); });
|
||||
this->container().partiallySort(number, [ & ](const OBJ & a, const OBJ & b) { return a.getRelativeDistance() < b.getRelativeDistance(); });
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
@@ -126,4 +128,3 @@ namespace BlackMisc
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace BlackMisc
|
||||
//! Find 0..n objects within range of given coordinate
|
||||
//! \param coordinate other position
|
||||
//! \param range within range of other position
|
||||
//! \return
|
||||
CONTAINER findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const;
|
||||
|
||||
//! Find 0..n objects closest to the given coordinate.
|
||||
@@ -95,7 +94,7 @@ namespace BlackMisc
|
||||
void removeIfOutsideRange(const BlackMisc::Geo::ICoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &maxDistance, bool updateValues);
|
||||
|
||||
//! Calculate distances
|
||||
void calculcateDistanceAndBearingToPosition(const BlackMisc::Geo::ICoordinateGeodetic &position);
|
||||
void calculcateAndUpdateRelativeDistanceAndBearing(const BlackMisc::Geo::ICoordinateGeodetic &position);
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
|
||||
@@ -107,8 +107,10 @@ namespace BlackMisc
|
||||
GlobalIndexCVisibilityLayer = 4600,
|
||||
GlobalIndexCWeatherScenario = 4700,
|
||||
GlobalIndexICoordinateGeodetic = 5000,
|
||||
GlobalIndexCCoordinateGeodetic = 5100,
|
||||
GlobalIndexICoordinateWithRelativePosition = 5100,
|
||||
GlobalIndexCCoordinateGeodetic = 5200,
|
||||
GlobalIndexCClient = 6000,
|
||||
GlobalIndexClientCapabilities = 6050, //!< used with map key
|
||||
GlobalIndexCUser = 6100,
|
||||
GlobalIndexCAuthenticatedUser = 6200,
|
||||
GlobalIndexCRole = 6300,
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace BlackMisc
|
||||
CCallsign cs(currentAircraft.getCallsign());
|
||||
if (currentAircraft.isEnabled())
|
||||
{
|
||||
CLength distance(currentAircraft.getDistanceToOwnAircraft());
|
||||
CLength distance(currentAircraft.getRelativeDistance());
|
||||
if (count >= maxAircraft ||
|
||||
(!maxRenderedDistance.isNull() && distance >= maxRenderedBoundary) ||
|
||||
(!maxRenderedBoundary.isNull() && distance >= maxRenderedBoundary))
|
||||
|
||||
@@ -288,8 +288,8 @@ namespace BlackMisc
|
||||
return this->m_callsign.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexPilot:
|
||||
return this->m_pilot.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexDistanceToOwnAircraft:
|
||||
return this->m_distanceToOwnAircraft.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexRelativeDistance:
|
||||
return this->m_relativeDistance.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexCom1System:
|
||||
return this->m_com1system.propertyByIndex(index.copyFrontRemoved());
|
||||
case IndexCom2System:
|
||||
@@ -309,8 +309,8 @@ namespace BlackMisc
|
||||
case IndexCombinedIcaoLiveryString:
|
||||
return CVariant::fromValue(this->getCombinedIcaoLiveryString());
|
||||
default:
|
||||
return (ICoordinateGeodetic::canHandleIndex(index)) ?
|
||||
ICoordinateGeodetic::propertyByIndex(index) :
|
||||
return (ICoordinateWithRelativePosition::canHandleIndex(index)) ?
|
||||
ICoordinateWithRelativePosition::propertyByIndex(index) :
|
||||
CValueObject::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
@@ -327,8 +327,8 @@ namespace BlackMisc
|
||||
case IndexPilot:
|
||||
this->m_pilot.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexDistanceToOwnAircraft:
|
||||
this->m_distanceToOwnAircraft.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
case IndexRelativeDistance:
|
||||
this->m_relativeDistance.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
break;
|
||||
case IndexCom1System:
|
||||
this->m_com1system.setPropertyByIndex(index.copyFrontRemoved(), variant);
|
||||
@@ -365,7 +365,14 @@ namespace BlackMisc
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported");
|
||||
break;
|
||||
default:
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
ICoordinateWithRelativePosition::setPropertyByIndex(index, variant);
|
||||
}
|
||||
else
|
||||
{
|
||||
CValueObject::setPropertyByIndex(index, variant);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -381,8 +388,8 @@ namespace BlackMisc
|
||||
case IndexPilot:
|
||||
return this->m_pilot.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getPilot());
|
||||
case IndexSituation:
|
||||
case IndexDistanceToOwnAircraft:
|
||||
return this->m_distanceToOwnAircraft.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getDistanceToOwnAircraft());
|
||||
case IndexRelativeDistance:
|
||||
return this->m_relativeDistance.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getRelativeDistance());
|
||||
case IndexCom1System:
|
||||
return m_com1system.getFrequencyActive().comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCom1System().getFrequencyActive());
|
||||
case IndexCom2System:
|
||||
@@ -404,6 +411,10 @@ namespace BlackMisc
|
||||
case IndexFastPositionUpdates:
|
||||
return Compare::compare(this->m_fastPositionUpdates, compareValue.fastPositionUpdates());
|
||||
default:
|
||||
if (ICoordinateWithRelativePosition::canHandleIndex(index))
|
||||
{
|
||||
return ICoordinateWithRelativePosition::comparePropertyByIndex(index, compareValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Comapre failed");
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace BlackMisc
|
||||
{
|
||||
IndexCallsign = BlackMisc::CPropertyIndex::GlobalIndexCSimulatedAircraft,
|
||||
IndexPilot,
|
||||
IndexDistanceToOwnAircraft,
|
||||
IndexRelativeDistance,
|
||||
IndexCom1System,
|
||||
IndexCom2System,
|
||||
IndexTransponder,
|
||||
@@ -411,8 +411,8 @@ namespace BlackMisc
|
||||
BLACK_METAMEMBER(com2system),
|
||||
BLACK_METAMEMBER(transponder),
|
||||
BLACK_METAMEMBER(parts),
|
||||
BLACK_METAMEMBER(distanceToOwnAircraft),
|
||||
BLACK_METAMEMBER(bearingToOwnAircraft),
|
||||
BLACK_METAMEMBER(relativeDistance),
|
||||
BLACK_METAMEMBER(relativeBearing),
|
||||
BLACK_METAMEMBER(model),
|
||||
BLACK_METAMEMBER(enabled),
|
||||
BLACK_METAMEMBER(rendered),
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace BlackMisc
|
||||
{
|
||||
namespace Aviation
|
||||
{
|
||||
|
||||
CAtcStationList CTesting::createAtcStations(int number, bool byPropertyIndex)
|
||||
{
|
||||
CAtcStationList atcs;
|
||||
@@ -71,14 +70,14 @@ namespace BlackMisc
|
||||
station.setPropertyByIndex(CAtcStation::IndexIsOnline, CVariant::from(false));
|
||||
station.setPropertyByIndex(CAtcStation::IndexBookedFrom, CVariant::from(dtFrom));
|
||||
station.setPropertyByIndex(CAtcStation::IndexBookedUntil, CVariant::from(dtUntil));
|
||||
station.setPropertyByIndex(CAtcStation::IndexDistanceToOwnAircraft, CVariant::from(CLength(index + 1, CLengthUnit::NM())));
|
||||
station.setPropertyByIndex(CAtcStation::IndexRelativeDistance, CVariant::from(CLength(index + 1, CLengthUnit::NM())));
|
||||
}
|
||||
else
|
||||
{
|
||||
station = CAtcStation(CCallsign(cs), user,
|
||||
CFrequency(f, CFrequencyUnit::MHz()),
|
||||
geoPos, CLength(50, CLengthUnit::km()), false, dtFrom, dtUntil);
|
||||
station.setDistanceToOwnAircraft(CLength(index + 1, CLengthUnit::NM()));
|
||||
station.setRelativeDistance(CLength(index + 1, CLengthUnit::NM()));
|
||||
}
|
||||
|
||||
station.setVoiceRoomUrl("vvl://foo.bar.baz/room" + QString::number(index));
|
||||
@@ -102,7 +101,7 @@ namespace BlackMisc
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexController, CUser::IndexRealName}).toQString());
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexPosition, CCoordinateGeodetic::IndexLatitudeAsString}).toQString());
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexPosition, CCoordinateGeodetic::IndexLongitudeAsString}).toQString());
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexDistanceToOwnAircraft, CLength::IndexValueRounded2DigitsWithUnit}).toQString());
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexRelativeDistance, CLength::IndexValueRounded2DigitsWithUnit}).toQString());
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexBookedFrom}).toDateTime().toString("YYYY-mm-dd hh:mm"));
|
||||
r.append(station.propertyByIndex({ CAtcStation::IndexBookedUntil}).toDateTime().toString("YYYY-mm-dd hh:mm"));
|
||||
}
|
||||
@@ -112,7 +111,7 @@ namespace BlackMisc
|
||||
r.append(station.getController().getRealName());
|
||||
r.append(station.getPosition().latitudeAsString());
|
||||
r.append(station.getPosition().longitudeAsString());
|
||||
r.append(station.getDistanceToOwnAircraft().toQString(true));
|
||||
r.append(station.getRelativeDistance().toQString(true));
|
||||
r.append(station.getBookedFromUtc().toString("YYYY-mm-dd hh:mm"));
|
||||
r.append(station.getBookedUntilUtc().toString("YYYY-mm-dd hh:mm"));
|
||||
}
|
||||
@@ -138,7 +137,7 @@ namespace BlackMisc
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int p = i % s;
|
||||
atc.calculcateDistanceToOwnAircraft(pos.at(p));
|
||||
atc.calculcateAndUpdateRelativeDistance(pos.at(p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +171,5 @@ namespace BlackMisc
|
||||
c = CCoordinateGeodetic::fromWgs84(wgsLatLng.at(idx), wgsLatLng.at(idx + 1), h);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user