mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-04 16:56:53 +08:00
Ref T259, Ref T243 coordinate list and improved "find" functions in IGeoObjectList
This commit is contained in:
@@ -249,8 +249,7 @@ namespace BlackMisc
|
||||
|
||||
void CCoordinateGeodetic::setGeodeticHeightToNull()
|
||||
{
|
||||
static const CAltitude na = CAltitude(0, CAltitude::MeanSeaLevel, CLengthUnit::nullUnit());
|
||||
this->setGeodeticHeight(na);
|
||||
this->setGeodeticHeight(CAltitude::null());
|
||||
}
|
||||
|
||||
CCoordinateGeodetic &CCoordinateGeodetic::switchUnit(const CLengthUnit &unit)
|
||||
|
||||
@@ -95,6 +95,9 @@ namespace BlackMisc
|
||||
//! Geodetic height null?
|
||||
bool isGeodeticHeightNull() const { return this->geodeticHeight().isNull(); }
|
||||
|
||||
//! Geodetic height not null and Aviation::CAltitude::MeanSeaLevel
|
||||
bool hasMSLGeodeticHeight() const { return !this->geodeticHeight().isNull() && this->geodeticHeight().getReferenceDatum() == Aviation::CAltitude::MeanSeaLevel; }
|
||||
|
||||
//! Is null, means vector x, y, z == 0
|
||||
//! \remark this is a default implementation, concrete implementations of ICoordinateGeodetic might override it
|
||||
virtual bool isNull() const { return this->normalVector().isNull(); }
|
||||
|
||||
31
src/blackmisc/geo/coordinategeodeticlist.cpp
Normal file
31
src/blackmisc/geo/coordinategeodeticlist.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2018
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "coordinategeodeticlist.h"
|
||||
|
||||
#include <QJsonValue>
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
CCoordinateGeodeticList::CCoordinateGeodeticList()
|
||||
{ }
|
||||
|
||||
CCoordinateGeodeticList::CCoordinateGeodeticList(const CSequence<CCoordinateGeodetic> &other) :
|
||||
CSequence<CCoordinateGeodetic>(other)
|
||||
{ }
|
||||
|
||||
CCoordinateGeodeticList::CCoordinateGeodeticList(std::initializer_list<CCoordinateGeodetic> il) :
|
||||
CSequence<CCoordinateGeodetic>(il)
|
||||
{ }
|
||||
} // namespace
|
||||
} // namespace
|
||||
57
src/blackmisc/geo/coordinategeodeticlist.h
Normal file
57
src/blackmisc/geo/coordinategeodeticlist.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright (C) 2018
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_GEO_COORDINATEGEODETICLIST_H
|
||||
#define BLACKMISC_GEO_COORDINATEGEODETICLIST_H
|
||||
|
||||
#include "coordinategeodetic.h"
|
||||
#include "geoobjectlist.h"
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/collection.h"
|
||||
#include "blackmisc/json.h"
|
||||
#include "blackmisc/sequence.h"
|
||||
#include "blackmisc/variant.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QMetaType>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace Geo
|
||||
{
|
||||
//! Value object encapsulating a list of coordinates.
|
||||
class BLACKMISC_EXPORT CCoordinateGeodeticList :
|
||||
public CSequence<CCoordinateGeodetic>,
|
||||
public IGeoObjectList<CCoordinateGeodetic, CCoordinateGeodeticList>,
|
||||
public Mixin::MetaType<CCoordinateGeodeticList>,
|
||||
public Mixin::JsonOperators<CCoordinateGeodeticList>
|
||||
{
|
||||
public:
|
||||
BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CCoordinateGeodeticList)
|
||||
|
||||
//! Default constructor.
|
||||
CCoordinateGeodeticList();
|
||||
|
||||
//! Construct by coordinates
|
||||
CCoordinateGeodeticList(std::initializer_list<CCoordinateGeodetic> coordinates);
|
||||
|
||||
//! Construct from a base class object.
|
||||
CCoordinateGeodeticList(const CSequence<CCoordinateGeodetic> &other);
|
||||
};
|
||||
} //namespace
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::Geo::CCoordinateGeodeticList)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CCollection<BlackMisc::Geo::CCoordinateGeodetic>)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CSequence<BlackMisc::Geo::CCoordinateGeodetic>)
|
||||
|
||||
#endif //guard
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "blackmisc/geo/latitude.h"
|
||||
#include "blackmisc/geo/longitude.h"
|
||||
#include "blackmisc/geo/coordinategeodetic.h"
|
||||
#include "blackmisc/geo/coordinategeodeticlist.h"
|
||||
#include "blackmisc/geo/elevationplane.h"
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
*/
|
||||
|
||||
#include "blackmisc/geo/geoobjectlist.h"
|
||||
#include "blackmisc/geo/geo.h"
|
||||
#include "blackmisc/geo/coordinategeodetic.h"
|
||||
#include "blackmisc/aviation/atcstationlist.h"
|
||||
#include "blackmisc/aviation/airportlist.h"
|
||||
#include "blackmisc/aviation/atcstationlist.h"
|
||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||
#include "blackmisc/aviation/aircraftsituationlist.h"
|
||||
#include "blackmisc/simulation/simulatedaircraftlist.h"
|
||||
#include "blackmisc/simulation/xplane/navdatareference.h"
|
||||
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
|
||||
namespace BlackMisc
|
||||
@@ -51,6 +53,68 @@ namespace BlackMisc
|
||||
});
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
CONTAINER IGeoObjectList<OBJ, CONTAINER>::findWithGeodeticMSLHeight() const
|
||||
{
|
||||
return this->container().findBy(&OBJ::hasMSLGeodeticHeight, true);
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
bool IGeoObjectList<OBJ, CONTAINER>::containsObjectInRange(const ICoordinateGeodetic &coordinate, const CLength &range) const
|
||||
{
|
||||
return this->container().containsBy([&](const OBJ & geoObj)
|
||||
{
|
||||
const CLength d = coordinate.calculateGreatCircleDistance(geoObj);
|
||||
return d <= range;
|
||||
});
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
typename IGeoObjectList<OBJ, CONTAINER>::MinMaxAverageHeight IGeoObjectList<OBJ, CONTAINER>::findMinMaxAverageHeight() const
|
||||
{
|
||||
MinMaxAverageHeight stats{ CAltitude::null(), CAltitude::null(), CAltitude::null(), 0 };
|
||||
int c = 0;
|
||||
double avgFt = 0;
|
||||
for (const OBJ &obj : this->container())
|
||||
{
|
||||
if (!obj.hasMSLGeodeticHeight()) { continue; }
|
||||
const CAltitude alt = obj.geodeticHeight();
|
||||
if (std::get<0>(stats).isNull() || std::get<0>(stats) > alt)
|
||||
{
|
||||
std::get<0>(stats) = alt;
|
||||
}
|
||||
if (std::get<1>(stats).isNull() || std::get<1>(stats) < alt)
|
||||
{
|
||||
std::get<1>(stats) = alt;
|
||||
}
|
||||
avgFt += alt.value(CLengthUnit::ft());
|
||||
}
|
||||
|
||||
std::get<2>(stats) = CAltitude(avgFt / c, CAltitude::MeanSeaLevel, CLengthUnit::ft());
|
||||
std::get<3>(stats) = c;
|
||||
return stats;
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
int IGeoObjectList<OBJ, CONTAINER>::removeOutsideRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range)
|
||||
{
|
||||
const int size = this->container().size();
|
||||
const CONTAINER copy = this->container().findWithinRange(coordinate, range);
|
||||
const int d = size - copy.size();
|
||||
if (d > 0) { *this = copy; }
|
||||
return d;
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
int IGeoObjectList<OBJ, CONTAINER>::removeWithoutGeodeticHeight()
|
||||
{
|
||||
const int size = this->container().size();
|
||||
const CONTAINER copy = this->findWithGeodeticMSLHeight();
|
||||
const int d = size - copy.size();
|
||||
if (d > 0) { *this = copy; }
|
||||
return d;
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
CONTAINER IGeoObjectList<OBJ, CONTAINER>::findClosest(int number, const ICoordinateGeodetic &coordinate) const
|
||||
{
|
||||
@@ -58,10 +122,45 @@ namespace BlackMisc
|
||||
{
|
||||
return calculateEuclideanDistanceSquared(a, coordinate) < calculateEuclideanDistanceSquared(b, coordinate);
|
||||
});
|
||||
closest.truncate(number);
|
||||
Q_ASSERT_X(closest.size() <= number, Q_FUNC_INFO, "size exceeded");
|
||||
return closest;
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
OBJ IGeoObjectList<OBJ, CONTAINER>::findClosestWithinRange(const ICoordinateGeodetic &coordinate, const CLength &range) const
|
||||
{
|
||||
OBJ closest;
|
||||
CLength distance = CLength::null();
|
||||
for (const OBJ &obj : this->container())
|
||||
{
|
||||
const CLength d = coordinate.calculateGreatCircleDistance(obj);
|
||||
if (d > range) { continue; }
|
||||
if (distance.isNull() || distance > d)
|
||||
{
|
||||
distance = d;
|
||||
closest = obj;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
void IGeoObjectList<OBJ, CONTAINER>::sortByEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate)
|
||||
{
|
||||
this->container().sort([ & ](const OBJ & a, const OBJ & b)
|
||||
{
|
||||
return calculateEuclideanDistanceSquared(a, coordinate) < calculateEuclideanDistanceSquared(b, coordinate);
|
||||
});
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
CONTAINER IGeoObjectList<OBJ, CONTAINER>::sortedByEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate)
|
||||
{
|
||||
CONTAINER copy(this->container());
|
||||
copy.sortByEuclideanDistanceSquared(coordinate);
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <class OBJ, class CONTAINER>
|
||||
void IGeoObjectWithRelativePositionList<OBJ, CONTAINER>::calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position)
|
||||
{
|
||||
@@ -111,7 +210,7 @@ namespace BlackMisc
|
||||
if (this->container().size() >= number) { return (this->container()); }
|
||||
CONTAINER closest(this->container());
|
||||
closest.partiallySortByDistanceToOwnAircraft(number);
|
||||
closest.truncate(number);
|
||||
Q_ASSERT_X(closest.size() <= number, Q_FUNC_INFO, "size exceeded");
|
||||
return closest;
|
||||
}
|
||||
|
||||
@@ -120,9 +219,10 @@ namespace BlackMisc
|
||||
//! \cond PRIVATE
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAtcStation, BlackMisc::Aviation::CAtcStationList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAirport, BlackMisc::Aviation::CAirportList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAircraftSituation, BlackMisc::Aviation::CAircraftSituationList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Geo::CCoordinateGeodetic, BlackMisc::Geo::CCoordinateGeodeticList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Simulation::CSimulatedAircraft, BlackMisc::Simulation::CSimulatedAircraftList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectList<BlackMisc::Simulation::XPlane::CNavDataReference, BlackMisc::Simulation::XPlane::CNavDataReferenceList>;
|
||||
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectWithRelativePositionList<BlackMisc::Aviation::CAtcStation, BlackMisc::Aviation::CAtcStationList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectWithRelativePositionList<BlackMisc::Aviation::CAirport, BlackMisc::Aviation::CAirportList>;
|
||||
template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IGeoObjectWithRelativePositionList<BlackMisc::Simulation::CSimulatedAircraft, BlackMisc::Simulation::CSimulatedAircraftList>;
|
||||
|
||||
@@ -12,9 +12,13 @@
|
||||
#ifndef BLACKMISC_GEO_GEOOBJECTLIST_H
|
||||
#define BLACKMISC_GEO_GEOOBJECTLIST_H
|
||||
|
||||
#include "blackmisc/aviation/altitude.h"
|
||||
#include "blackmisc/pq/length.h"
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/sequence.h"
|
||||
#include "blackmisc/pq/length.h"
|
||||
|
||||
#include <QList>
|
||||
#include <tuple>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
@@ -24,6 +28,8 @@ namespace BlackMisc
|
||||
class CAtcStationList;
|
||||
class CAirport;
|
||||
class CAirportList;
|
||||
class CAircraftSituation;
|
||||
class CAircraftSituationList;
|
||||
}
|
||||
|
||||
namespace Simulation
|
||||
@@ -41,19 +47,48 @@ namespace BlackMisc
|
||||
namespace Geo
|
||||
{
|
||||
class ICoordinateGeodetic;
|
||||
class CCoordinateGeodetic;
|
||||
class CCoordinateGeodeticList;
|
||||
|
||||
//! List of objects with geo coordinates.
|
||||
template<class OBJ, class CONTAINER>
|
||||
class IGeoObjectList
|
||||
{
|
||||
public:
|
||||
//! For statistics
|
||||
using MinMaxAverageHeight = std::tuple<Aviation::CAltitude, Aviation::CAltitude, Aviation::CAltitude, int>;
|
||||
|
||||
//! Find 0..n objects within range of given coordinate
|
||||
//! \param coordinate other position
|
||||
//! \param range within range of other position
|
||||
CONTAINER findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const;
|
||||
//! \param coordinate other position
|
||||
//! \param range within range of other position
|
||||
CONTAINER findWithinRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const;
|
||||
|
||||
//! Elements with geodetic height (only MSL)
|
||||
CONTAINER findWithGeodeticMSLHeight() const;
|
||||
|
||||
//! Any object in range
|
||||
bool containsObjectInRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const;
|
||||
|
||||
//! Find min/max/average height
|
||||
MinMaxAverageHeight findMinMaxAverageHeight() const;
|
||||
|
||||
//! Remove outside range
|
||||
int removeOutsideRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range);
|
||||
|
||||
//! Remove if there is no geodetic height
|
||||
int removeWithoutGeodeticHeight();
|
||||
|
||||
//! Find 0..n objects closest to the given coordinate.
|
||||
CONTAINER findClosest(int number, const BlackMisc::Geo::ICoordinateGeodetic &coordinate) const;
|
||||
CONTAINER findClosest(int number, const ICoordinateGeodetic &coordinate) const;
|
||||
|
||||
//! Find closest within range to the given coordinate
|
||||
OBJ findClosestWithinRange(const ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const;
|
||||
|
||||
//! Sort by distance
|
||||
void sortByEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate);
|
||||
|
||||
//! Sorted by distance
|
||||
CONTAINER sortedByEuclideanDistanceSquared(const ICoordinateGeodetic &coordinate);
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
@@ -69,6 +104,8 @@ namespace BlackMisc
|
||||
//! \cond PRIVATE
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAtcStation, BlackMisc::Aviation::CAtcStationList>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAirport, BlackMisc::Aviation::CAirportList>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Aviation::CAircraftSituation, BlackMisc::Aviation::CAircraftSituationList>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Geo::CCoordinateGeodetic, BlackMisc::Geo::CCoordinateGeodeticList>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Simulation::CSimulatedAircraft, BlackMisc::Simulation::CSimulatedAircraftList>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IGeoObjectList<BlackMisc::Simulation::XPlane::CNavDataReference, BlackMisc::Simulation::XPlane::CNavDataReferenceList>;
|
||||
//! \endcond
|
||||
@@ -79,7 +116,7 @@ namespace BlackMisc
|
||||
{
|
||||
public:
|
||||
//! Calculate distances, then sort by range
|
||||
void sortByRange(const BlackMisc::Geo::ICoordinateGeodetic &position, bool updateValues);
|
||||
void sortByRange(const ICoordinateGeodetic &position, bool updateValues);
|
||||
|
||||
//! If distance is already set, just sort
|
||||
void sortByDistanceToOwnAircraft();
|
||||
@@ -91,10 +128,10 @@ namespace BlackMisc
|
||||
CONTAINER getClosestObjects(int number) const;
|
||||
|
||||
//! Calculate distances, remove if outside range
|
||||
void removeIfOutsideRange(const BlackMisc::Geo::ICoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &maxDistance, bool updateValues);
|
||||
void removeIfOutsideRange(const ICoordinateGeodetic &position, const PhysicalQuantities::CLength &maxDistance, bool updateValues);
|
||||
|
||||
//! Calculate distances
|
||||
void calculcateAndUpdateRelativeDistanceAndBearing(const BlackMisc::Geo::ICoordinateGeodetic &position);
|
||||
void calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position);
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace BlackMisc
|
||||
void registerMetadata()
|
||||
{
|
||||
CCoordinateGeodetic::registerMetadata();
|
||||
CCoordinateGeodeticList::registerMetadata();
|
||||
CLatitude::registerMetadata();
|
||||
CLongitude::registerMetadata();
|
||||
CElevationPlane::registerMetadata();
|
||||
|
||||
Reference in New Issue
Block a user