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);
void AirportDiagram::setApproachExtensionDistance(double distanceNm)
{
+ if (m_approachDistanceNm == distanceNm) {
+ return;
+ }
+
m_approachDistanceNm = distanceNm;
recomputeBounds(true);
update();
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);
}
}
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<double>::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()
void doComputeBounds() Q_DECL_OVERRIDE;
private:
-
-
-
- FGAirportRef m_airport;
-
struct RunwayData {
QPointF p1, p2;
int widthM;
FGRunwayRef runway;
};
- QVector<RunwayData> m_runways;
-
struct TaxiwayData {
QPointF p1, p2;
int widthM;
}
};
- QVector<TaxiwayData> m_taxiways;
- QVector<QPainterPath> m_pavements;
-
struct ParkingData
{
QPointF pt;
FGParkingRef parking;
};
- QVector<ParkingData> m_parking;
-
struct HelipadData
{
QPointF pt;
FGHelipadRef helipad;
};
- QVector<HelipadData> m_helipads;
-
void buildTaxiways();
void buildPavements();
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<RunwayData> m_runways;
+ QVector<TaxiwayData> m_taxiways;
+ QVector<QPainterPath> m_pavements;
+ QVector<ParkingData> m_parking;
+ QVector<HelipadData> 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