From c4ccc139af1b1861c9b00374a19030bb29ee328d Mon Sep 17 00:00:00 2001 From: Alexander Barthel Date: Thu, 30 Aug 2018 21:56:19 +0200 Subject: [PATCH] Now showing crab angle in compass rose. Also added display indicator for next waypoint in compass rose. Corrected display of crab angle in aircraft progress display. All #284 --- src/common/htmlinfobuilder.cpp | 19 +++++++---- src/common/symbolpainter.cpp | 2 +- src/mapgui/mappaintermark.cpp | 61 ++++++++++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/common/htmlinfobuilder.cpp b/src/common/htmlinfobuilder.cpp index 9e89d5699..37454dfa5 100644 --- a/src/common/htmlinfobuilder.cpp +++ b/src/common/htmlinfobuilder.cpp @@ -2580,15 +2580,20 @@ void HtmlInfoBuilder::aircraftProgressText(const atools::fs::sc::SimConnectAircr float legCourse = routeLeg.getCourseToRhumbMag(); html.row2(tr("Leg Course:"), locale.toString(legCourse, 'f', 0) + tr("°M")); - if(!less && userAircaft != nullptr) + if(!less && userAircaft != nullptr && userAircaft->isFlying()) { - // The angle between heading and track is known as the drift angle. - float driftAngle = normalizeCourse(userAircaft->getHeadingDegMag() - userAircaft->getTrackDegMag()); - // Crab angle is the amount of correction an aircraft must be turned into the wind in order to maintain the desired course. - float crabAngle = normalizeCourse(legCourse + driftAngle); - - html.row2(tr("Crab angle:"), locale.toString(crabAngle, 'f', 0) + tr("°M")); + float crabAngle = atools::geo::windCorrectedHeading(userAircaft->getWindSpeedKts(), + userAircaft->getWindDirectionDegT(), + routeLeg.getCourseToRhumbTrue(), + userAircaft->getTrueAirspeedKts()); + if(crabAngle < INVALID_COURSE_VALUE) + { + crabAngle = normalizeCourse(crabAngle - userAircaft->getMagVarDeg()); + html.row2(tr("Crab angle:"), locale.toString(crabAngle, 'f', 0) + tr("°M")); + } + else + html.row2(tr("Crab angle:")); } } diff --git a/src/common/symbolpainter.cpp b/src/common/symbolpainter.cpp index 3b0b1f3a2..6a5660e39 100644 --- a/src/common/symbolpainter.cpp +++ b/src/common/symbolpainter.cpp @@ -1054,7 +1054,7 @@ void SymbolPainter::textBoxF(QPainter *painter, const QStringList& texts, const // Draw the text QFontMetricsF metrics = painter->fontMetrics(); float h = static_cast(metrics.height()) - 1.f; - float yoffset = (texts.size() * h) / 2.f - static_cast(metrics.descent()); + float yoffset = (static_cast(texts.size() * h)) / 2.f - static_cast(metrics.descent()); painter->setPen(textPen); // Draw text in reverse order to avoid undercut diff --git a/src/mapgui/mappaintermark.cpp b/src/mapgui/mappaintermark.cpp index 97d133e7d..d890151eb 100644 --- a/src/mapgui/mappaintermark.cpp +++ b/src/mapgui/mappaintermark.cpp @@ -405,7 +405,8 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) Q_UNUSED(saver); Marble::GeoPainter *painter = context->painter; - Pos pos = mapWidget->getUserAircraft().getPosition(); + const atools::fs::sc::SimConnectUserAircraft& aircaft = mapWidget->getUserAircraft(); + Pos pos = aircaft.getPosition(); // Use either aircraft position or viewport center QRect viewport = painter->viewport(); @@ -432,7 +433,7 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) painter->setBrush(Qt::NoBrush); float lineWidth = context->szF(context->thicknessCompassRose, 2); QPen rosePen(QBrush(mapcolors::compassRoseColor), lineWidth, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin); - QPen rosePenSmall(QBrush(mapcolors::compassRoseColor), lineWidth / 8.f, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin); + QPen rosePenSmall(QBrush(mapcolors::compassRoseColor), lineWidth / 4.f, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin); QPen headingLinePen(QBrush(mapcolors::compassRoseColor), lineWidth, Qt::DotLine, Qt::RoundCap, Qt::MiterJoin); painter->setPen(rosePen); @@ -447,7 +448,7 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) painter->drawEllipse(centerPoint, 5, 5); // Collect points for tick marks and labels - float magVar = hasAircraft ? mapWidget->getUserAircraft().getMagVarDeg() : NavApp::getMagVar(pos); + float magVar = hasAircraft ? aircaft.getMagVarDeg() : NavApp::getMagVar(pos); QVector endpoints; QVector endpointsScreen; for(float angle = 0.f; angle < 360.f; angle += 5) @@ -499,12 +500,12 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) { // Solid track line painter->setPen(rosePen); - float trackTrue = mapWidget->getUserAircraft().getTrackDegTrue(); + float trackTrue = aircaft.getTrackDegTrue(); Pos trueTrackPos = pos.endpoint(radiusMeter, trackTrue); drawLine(context, Line(pos, trueTrackPos)); // Dotted heading line - float headingTrue = mapWidget->getUserAircraft().getHeadingDegTrue(); + float headingTrue = aircaft.getHeadingDegTrue(); Pos trueHeadingPos = pos.endpoint(radiusMeter, headingTrue); painter->setPen(headingLinePen); drawLine(context, Line(pos, trueHeadingPos)); @@ -560,7 +561,7 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) float trackTrue = 0.f; if(hasAircraft) // Solid track line - trackTrue = mapWidget->getUserAircraft().getTrackDegTrue(); + trackTrue = aircaft.getTrackDegTrue(); // Distance labels along track line context->szFont(context->textSizeCompassRose * 0.8f); @@ -574,13 +575,59 @@ void MapPainterMark::paintCompassRose(const PaintContext *context) if(hasAircraft) { + const Route& route = NavApp::getRouteConst(); + + if(route.size() > 1 && aircaft.isFlying()) + { + bool isCorrected = false; + int activeLegCorrected = route.getActiveLegIndexCorrected(&isCorrected); + if(activeLegCorrected != map::INVALID_INDEX_VALUE) + { + // Draw crab angle if flight plan is available ======================== + + // If approaching an initial fix use corrected version + int activeLeg = route.getActiveLegIndex(); + const RouteLeg& routeLeg = activeLeg != map::INVALID_INDEX_VALUE && isCorrected ? + route.at(activeLeg) : route.at(activeLegCorrected); + + // Crab angle is the amount of correction an aircraft must be turned into the wind in order to maintain the desired course. + float crabAngle = windCorrectedHeading(aircaft.getWindSpeedKts(), aircaft.getWindDirectionDegT(), + routeLeg.getCourseToRhumbTrue(), aircaft.getTrueAirspeedKts()); + + Pos crabPos = pos.endpoint(radiusMeter, crabAngle); + painter->setPen(rosePen); + painter->setBrush(OptionData::instance().getFlightplanActiveSegmentColor()); + + QPointF crabScreenPos = wToSF(crabPos); + painter->drawEllipse(crabScreenPos, lineWidth * 3, lineWidth * 3); + + float crs = normalizeCourse(aircaft.getPosition().angleDegToRhumb(routeLeg.getPosition())); + + // Draw small line to show course to next waypoint ======================== + if(crs < INVALID_COURSE_VALUE) + { + Pos endPt = pos.endpoint(radiusMeter, crs); + Line crsLine(pos.interpolate(endPt, radiusMeter, 0.92f), endPt); + painter->setPen(QPen(mapcolors::routeOutlineColor, context->sz(context->thicknessFlightplan, 7), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + drawLineStraight(context, crsLine); + + painter->setPen(QPen(OptionData::instance().getFlightplanActiveSegmentColor(), + context->sz(context->thicknessFlightplan, 4), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + drawLineStraight(context, crsLine); + } + } + } + // Aircraft track label at end of track line ====================================================== QPointF trueTrackTextPoint = wToSF(pos.endpoint(radiusMeter * 1.1f, trackTrue)); if(!trueTrackTextPoint.isNull()) { + painter->setPen(mapcolors::compassRoseTextColor); context->szFont(context->textSizeCompassRose); QString text = - tr("%1°M").arg(QString::number(atools::roundToInt(mapWidget->getUserAircraft().getTrackDegMag()))); + tr("%1°M").arg(QString::number(atools::roundToInt(aircaft.getTrackDegMag()))); symbolPainter->textBoxF(painter, {text, tr("TRK")}, painter->pen(), trueTrackTextPoint.x(), trueTrackTextPoint.y(), textatt::CENTER | textatt::ROUTE_BG_COLOR); }