1
0
Fork 0

Base diagram can draw airways

This commit is contained in:
James Turner 2018-08-11 22:01:52 +02:00
parent 69dbfc0a27
commit cd0b493426
2 changed files with 108 additions and 15 deletions

View file

@ -32,9 +32,13 @@
#include <Navaids/positioned.hxx> #include <Navaids/positioned.hxx>
#include <Airports/airport.hxx> #include <Airports/airport.hxx>
#include <Navaids/PolyLine.hxx> #include <Navaids/PolyLine.hxx>
#include <Navaids/NavDataCache.hxx>
#include <Navaids/airways.hxx>
#include "QtLauncher_fwd.hxx" #include "QtLauncher_fwd.hxx"
using namespace flightgear;
/* equatorial and polar earth radius */ /* equatorial and polar earth radius */
const double rec = 6378137; // earth radius, equator (?) const double rec = 6378137; // earth radius, equator (?)
const double rpol = 6356752.314; // earth radius, polar (?) const double rpol = 6356752.314; // earth radius, polar (?)
@ -103,7 +107,9 @@ void BaseDiagram::extendRect(QRectF &r, const QPointF &p)
QRect BaseDiagram::rect() const QRect BaseDiagram::rect() const
{ {
return QRect(0, 0, width(), height()); return QRect(0, 0,
static_cast<int>(width()),
static_cast<int>(height()));
} }
void BaseDiagram::paint(QPainter* p) void BaseDiagram::paint(QPainter* p)
@ -123,6 +129,7 @@ void BaseDiagram::paint(QPainter* p)
m_baseDeviceTransform = p->deviceTransform(); m_baseDeviceTransform = p->deviceTransform();
m_viewportTransform = transform(); m_viewportTransform = transform();
p->setWorldTransform(m_viewportTransform * m_baseDeviceTransform); p->setWorldTransform(m_viewportTransform * m_baseDeviceTransform);
m_projectedPositions.clear();
paintPolygonData(p); paintPolygonData(p);
paintNavaids(p); paintNavaids(p);
@ -196,9 +203,8 @@ void BaseDiagram::paintGeodVec(QPainter* painter, const flightgear::SGGeodVec& v
{ {
QVector<QPointF> projected; QVector<QPointF> projected;
projected.reserve(vec.size()); projected.reserve(vec.size());
flightgear::SGGeodVec::const_iterator it; for (auto v: vec) {
for (it=vec.begin(); it != vec.end(); ++it) { projected.append(project(v));
projected.append(project(*it));
} }
painter->drawPolyline(projected.data(), projected.size()); painter->drawPolyline(projected.data(), projected.size());
@ -224,7 +230,7 @@ public:
MapFilter(LauncherController::AircraftType aircraft) MapFilter(LauncherController::AircraftType aircraft)
{ {
// addType(FGPositioned::FIX); addType(FGPositioned::FIX);
addType(FGPositioned::NDB); addType(FGPositioned::NDB);
addType(FGPositioned::VOR); addType(FGPositioned::VOR);
@ -242,15 +248,13 @@ public:
virtual bool pass(FGPositioned* aPos) const virtual bool pass(FGPositioned* aPos) const
{ {
bool ok = TypeFilter::pass(aPos); bool ok = TypeFilter::pass(aPos);
// fix-filtering code disabled since fixed are entirely disabled
#if 0
if (ok && (aPos->type() == FGPositioned::FIX)) { if (ok && (aPos->type() == FGPositioned::FIX)) {
// ignore fixes which end in digits // ignore fixes which end in digits
if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) { if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) {
return false; return false;
} }
} }
#endif
return ok; return ok;
} }
}; };
@ -301,6 +305,9 @@ void BaseDiagram::paintNavaids(QPainter* painter)
ports.resize(40); ports.resize(40);
} }
// paint airways underneath
paintAirways(painter, navaids);
m_labelRects.clear(); m_labelRects.clear();
m_labelRects.reserve(items.size()); m_labelRects.reserve(items.size());
painter->setTransform(m_baseDeviceTransform); painter->setTransform(m_baseDeviceTransform);
@ -316,6 +323,65 @@ void BaseDiagram::paintNavaids(QPainter* painter)
painter->restore(); painter->restore();
} }
void BaseDiagram::paintAirways(QPainter* painter, const FGPositionedList& navs)
{
// FIXME: specify the network
struct AirwaySegment
{
AirwaySegment(PositionedID t, PositionedID f, int a) :
to(t), from(f), airway(a)
{}
PositionedID to, from;
int airway;
};
std::vector<AirwaySegment> segmentsToDraw;
for (auto n : navs) {
const auto navGuid = n->guid();
AirwayEdgeVec edges = NavDataCache::instance()->airwayEdgesFrom(Airway::HighLevel, n->guid());
for (auto e : edges) {
const auto edgeEndGuid = e.second;
auto it = std::find_if(segmentsToDraw.begin(), segmentsToDraw.end(),
[edgeEndGuid, navGuid](const AirwaySegment& segment)
{
return ((segment.to == edgeEndGuid) && (segment.from == navGuid)) ||
((segment.from == edgeEndGuid) && (segment.to == navGuid));
});
if (it == segmentsToDraw.end()) {
segmentsToDraw.emplace_back(navGuid, edgeEndGuid, e.first);
}
}
}
QVector<QLineF> lines;
lines.reserve(segmentsToDraw.size());
for (auto seg : segmentsToDraw) {
QPointF p1 = projectedPosition(seg.from);
QPointF p2 = projectedPosition(seg.to);
const auto d = QVector2D(p2 - p1).normalized();
p1 += (d.toPointF() * 100);
p2 += (d.toPointF() * -100);
lines.append(QLineF(p1, p2));
}
QPen linePen(Qt::cyan, 1);
linePen.setCosmetic(true);
painter->setPen(linePen);
painter->drawLines(lines);
// find airway names
// draw airway name on top
}
QRect boundsOfLines(const QVector<QLineF>& lines) QRect boundsOfLines(const QVector<QLineF>& lines)
{ {
QRect r; QRect r;
@ -365,7 +431,7 @@ void BaseDiagram::paintNavaid(QPainter* painter, const FGPositionedRef &pos)
if (drawAsIcon) { if (drawAsIcon) {
QPixmap pm = iconForPositioned(pos); QPixmap pm = iconForPositioned(pos);
QPointF loc = m_viewportTransform.map(project(pos->geod())); QPointF loc = m_viewportTransform.map(projectedPosition(pos));
const auto sz = pm.size() / pm.devicePixelRatio(); const auto sz = pm.size() / pm.devicePixelRatio();
iconRect = QRect(QPoint(0,0), sz); iconRect = QRect(QPoint(0,0), sz);
iconRect.moveCenter(loc.toPoint()); iconRect.moveCenter(loc.toPoint());
@ -573,6 +639,7 @@ void BaseDiagram::wheelEvent(QWheelEvent *we)
void BaseDiagram::paintContents(QPainter* painter) void BaseDiagram::paintContents(QPainter* painter)
{ {
Q_UNUSED(painter);
} }
void BaseDiagram::recomputeBounds(bool resetZoom) void BaseDiagram::recomputeBounds(bool resetZoom)
@ -791,12 +858,7 @@ QPixmap BaseDiagram::iconForAirport(FGAirport* apt, const IconOptions& options)
QVector<QLineF> BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod& c) QVector<QLineF> BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod& c)
{ {
QVector<QLineF> r; QVector<QLineF> r;
for (auto rwy : apt->getRunwaysWithoutReciprocals()) {
const FGRunwayList& runways(apt->getRunwaysWithoutReciprocals());
FGRunwayList::const_iterator it;
for (it = runways.begin(); it != runways.end(); ++it) {
FGRunwayRef rwy = *it;
QPointF p1 = project(rwy->geod(), c); QPointF p1 = project(rwy->geod(), c);
QPointF p2 = project(rwy->end(), c); QPointF p2 = project(rwy->end(), c);
r.append(QLineF(p1, p2)); r.append(QLineF(p1, p2));
@ -837,3 +899,27 @@ QVector<QLineF> BaseDiagram::projectAirportRuwaysIntoRect(FGAirportRef apt, cons
return r; return r;
} }
QPointF BaseDiagram::projectedPosition(PositionedID pid) const
{
if (m_projectedPositions.contains(pid))
return m_projectedPositions.value(pid);
FGPositionedRef pos = NavDataCache::instance()->loadById(pid);
if (!pos)
return {};
QPointF pt = project(pos->geod());
m_projectedPositions[pid] = pt;
return pt;
}
QPointF BaseDiagram::projectedPosition(FGPositionedRef pos) const
{
if (m_projectedPositions.contains(pos->guid()))
return m_projectedPositions.value(pos->guid());
QPointF pt = project(pos->geod());
m_projectedPositions[pos->guid()] = pt;
return pt;
}

View file

@ -96,6 +96,11 @@ protected:
static SGGeod unproject(const QPointF &xy, const SGGeod &center); static SGGeod unproject(const QPointF &xy, const SGGeod &center);
void paintAirplaneIcon(QPainter *painter, const SGGeod &geod, int headingDeg); void paintAirplaneIcon(QPainter *painter, const SGGeod &geod, int headingDeg);
void paintAirways(QPainter* painter, const FGPositionedList& navs);
QPointF projectedPosition(PositionedID pid) const;
QPointF projectedPosition(FGPositionedRef pos) const;
private: private:
enum LabelPosition enum LabelPosition
{ {
@ -127,6 +132,8 @@ private:
mutable QHash<PositionedID, LabelPosition> m_labelPositions; mutable QHash<PositionedID, LabelPosition> m_labelPositions;
mutable QVector<QRect> m_labelRects; mutable QVector<QRect> m_labelRects;
mutable QHash<PositionedID, QPointF> m_projectedPositions;
static int textFlagsForLabelPosition(LabelPosition pos); static int textFlagsForLabelPosition(LabelPosition pos);
void splitItems(const FGPositionedList &in, FGPositionedList &navaids, FGPositionedList &ports); void splitItems(const FGPositionedList &in, FGPositionedList &navaids, FGPositionedList &ports);