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:
Klaus Basan
2016-07-12 03:01:50 +02:00
parent 64cee7fba8
commit b959972e0c
20 changed files with 302 additions and 129 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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