From 10e6ea7584090550fd09a5bd8177e9e9897b28d0 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 16 Jul 2016 16:57:19 +0100 Subject: [PATCH] Fix selection of parking positions by clicking. --- src/GUI/AirportDiagram.cxx | 120 ++++++++++++++++++++++--------------- src/GUI/AirportDiagram.hxx | 29 ++++----- 2 files changed, 88 insertions(+), 61 deletions(-) diff --git a/src/GUI/AirportDiagram.cxx b/src/GUI/AirportDiagram.cxx index 6f33a82fb..2d016b927 100644 --- a/src/GUI/AirportDiagram.cxx +++ b/src/GUI/AirportDiagram.cxx @@ -82,7 +82,8 @@ static double distanceToLineSegment(const QVector2D& p, const QVector2D& a, AirportDiagram::AirportDiagram(QWidget* pr) : BaseDiagram(pr), - m_approachDistanceNm(-1.0) + m_approachDistanceNm(-1.0), + m_helipadIcon(":/heliport-icon") { m_parkingIconPath.moveTo(0,0); m_parkingIconPath.lineTo(-16, -16); @@ -158,6 +159,10 @@ void AirportDiagram::setSelectedParking(FGParkingRef park) void AirportDiagram::setApproachExtensionDistance(double distanceNm) { + if (m_approachDistanceNm == distanceNm) { + return; + } + m_approachDistanceNm = distanceNm; recomputeBounds(true); update(); @@ -335,15 +340,14 @@ void AirportDiagram::paintContents(QPainter* p) void AirportDiagram::drawHelipads(QPainter* painter) { QTransform t = painter->transform(); - QPixmap icon(":/heliport-icon"); - QRect r = icon.rect(); + QRect r = m_helipadIcon.rect(); r.moveCenter(QPoint(0, 0)); Q_FOREACH(const HelipadData& p, m_helipads) { painter->setTransform(t); painter->translate(p.pt); - painter->drawPixmap(r, icon); + painter->drawPixmap(r, m_helipadIcon); } } @@ -446,67 +450,89 @@ void AirportDiagram::drawILS(QPainter* painter, FGRunwayRef runway) const painter->drawLine(endR, endCentre); } -static double pointDistance(const QPointF& p1, const QPointF& p2) -{ - QPointF d = p2 - p1; - return ::sqrt((d.x() * d.x()) + (d.y() * d.y())); -} - void AirportDiagram::mouseReleaseEvent(QMouseEvent* me) { - if (m_didPan) - return; // ignore panning drag+release ops here + if (me->button() != Qt::LeftButton) { + return; + } QTransform t(transform()); - double minDist = std::numeric_limits::max(); - FGRunwayRef bestRunway; - FGHelipadRef bestHelipad; - FGParkingRef bestParking; - Q_FOREACH(const RunwayData& r, m_runways) { - QPointF p1(t.map(r.p1)), p2(t.map(r.p2)); - double t; - double d = distanceToLineSegment(QVector2D(me->pos()), - QVector2D(p1), - QVector2D(p2), &t); - if (d < minDist) { - if (t > 0.5) { - bestRunway = r.runway->reciprocalRunway(); + QPainterPath pp = pathForRunway(r, t); + if (pp.contains(me->pos())) { + // check which end was clicked + QPointF p1(t.map(r.p1)), p2(t.map(r.p2)); + double param; + distanceToLineSegment(QVector2D(me->pos()), QVector2D(p1), QVector2D(p2), ¶m); + if (param > 0.5) { + emit clickedRunway(r.runway->reciprocalRunway()); } else { - bestRunway = r.runway; + emit clickedRunway(r.runway); } - minDist = d; + return; } - } + } // of runways iteration Q_FOREACH(const ParkingData& parking, m_parking) { - double d = pointDistance(me->pos(), t.map(parking.pt)); - if (d < minDist) { - bestParking = parking.parking; - bestRunway.clear(); - minDist = d; + QPainterPath pp = pathForParking(parking, t); + if (pp.contains(me->pos())) { + emit clickedParking(parking.parking); + return; } } + Q_FOREACH(const HelipadData& pad, m_helipads) { - double d = pointDistance(me->pos(), t.map(pad.pt)); - if (d < minDist) { - bestHelipad = pad.helipad; - bestRunway.clear(); - bestParking.clear(); - minDist = d; + QPainterPath pp = pathForHelipad(pad, t); + if (pp.contains(me->pos())) { + emit clickedHelipad(pad.helipad); + return; } } +} - - if (minDist < 16.0) { - if (bestRunway) - emit clickedRunway(bestRunway); - else if (bestParking) - emit clickedParking(bestParking); - else if (bestHelipad) - emit clickedHelipad(bestHelipad); +QPainterPath AirportDiagram::pathForRunway(const RunwayData& r, const QTransform& t) const +{ + QPainterPath pp; + double halfWidth = r.widthM * 0.5; + QVector2D v = QVector2D(r.p2 - r.p1); + v.normalize(); + QVector2D halfVec = QVector2D(v.y(), -v.x()) * halfWidth; + + pp.moveTo(r.p1 - halfVec.toPointF()); + pp.lineTo(r.p1 + halfVec.toPointF()); + pp.lineTo(r.p2 + halfVec.toPointF()); + pp.lineTo(r.p2 - halfVec.toPointF()); + pp.closeSubpath(); + + return t.map(pp); +} + +QPainterPath AirportDiagram::pathForParking(const ParkingData& p, const QTransform& t) const +{ + bool useLeftIcon = false; + double hdg = p.parking->getHeading(); + + if (hdg > 180.0) { + hdg += 90; + useLeftIcon = true; + } else { + hdg -= 90; } + + QTransform x = t; + x.translate(p.pt.x(), p.pt.y()); + x.rotate(hdg); + return x.map(useLeftIcon ? m_parkingIconLeftPath : m_parkingIconPath); +} + +QPainterPath AirportDiagram::pathForHelipad(const HelipadData& h, const QTransform& t) const +{ + QPainterPath pp; + QRect r = m_helipadIcon.rect(); + r.moveCenter(QPoint(0, 0)); + pp.addEllipse(r); + return t.map(pp); } void AirportDiagram::buildTaxiways() diff --git a/src/GUI/AirportDiagram.hxx b/src/GUI/AirportDiagram.hxx index 477881100..101da6258 100644 --- a/src/GUI/AirportDiagram.hxx +++ b/src/GUI/AirportDiagram.hxx @@ -59,19 +59,12 @@ protected: void doComputeBounds() Q_DECL_OVERRIDE; private: - - - - FGAirportRef m_airport; - struct RunwayData { QPointF p1, p2; int widthM; FGRunwayRef runway; }; - QVector m_runways; - struct TaxiwayData { QPointF p1, p2; int widthM; @@ -82,25 +75,18 @@ private: } }; - QVector m_taxiways; - QVector m_pavements; - struct ParkingData { QPointF pt; FGParkingRef parking; }; - QVector m_parking; - struct HelipadData { QPointF pt; FGHelipadRef helipad; }; - QVector m_helipads; - void buildTaxiways(); void buildPavements(); @@ -113,11 +99,26 @@ private: void drawHelipads(QPainter *painter); + QPainterPath pathForRunway(const RunwayData &r, const QTransform &t) const; + QPainterPath pathForHelipad(const HelipadData &h, const QTransform &t) const; + QPainterPath pathForParking(const ParkingData &p, const QTransform &t) const; + +private: + FGAirportRef m_airport; + + QVector m_runways; + QVector m_taxiways; + QVector m_pavements; + QVector m_parking; + QVector m_helipads; + QPainterPath m_parkingIconPath, // arrow points right m_parkingIconLeftPath; // arrow points left double m_approachDistanceNm; FGRunwayRef m_selectedRunway; FGParkingRef m_selectedParking; + + QPixmap m_helipadIcon; }; #endif // of GUI_AIRPORT_DIAGRAM_HXX -- 2.39.5