mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-27 11:05:44 +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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user