void GlideComputerStats::OnClimbBase(fixed StartAlt) { flightstats.AddClimbBase(Calculated().climb_start_time - Calculated().flight.takeoff_time, StartAlt); }
bool ButtonLabel::ExpandMacros(const TCHAR *In, TCHAR *OutBuffer, size_t Size) { // ToDo, check Buffer Size bool invalid = false; CopyString(OutBuffer, In, Size); if (_tcsstr(OutBuffer, _T("$(")) == NULL) return false; if (_tcsstr(OutBuffer, _T("$(CheckAirspace)"))) { if (airspace_database.empty()) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckAirspace)"), _T(""), Size); } invalid |= ExpandTaskMacros(OutBuffer, Size, Calculated(), GetComputerSettings()); if (_tcsstr(OutBuffer, _T("$(CheckFLARM)"))) { if (!Basic().flarm.available) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckFLARM)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckCircling)"))) { if (!Calculated().circling) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckCircling)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckVega)"))) { if (devVarioFindVega()== NULL) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckVega)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckReplay)"))) { if (CommonInterface::MovementDetected()) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckReplay)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckWaypointFile)"))) { invalid |= way_points.IsEmpty(); ReplaceInString(OutBuffer, _T("$(CheckWaypointFile)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckLogger)"))) { invalid |= Basic().gps.replay; ReplaceInString(OutBuffer, _T("$(CheckLogger)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckFLARM)"))) { if (!Basic().flarm.available) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckFLARM)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckNet)"))) { #ifndef HAVE_NET invalid = true; #endif ReplaceInString(OutBuffer, _T("$(CheckNet)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckTerrain)"))) { if (!Calculated().terrain_valid) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckTerrain)"), _T(""), Size); } CondReplaceInString(logger.IsLoggerActive(), OutBuffer, _T("$(LoggerActive)"), _("Stop"), _("Start"), Size); if (_tcsstr(OutBuffer, _T("$(SnailTrailToggleName)"))) { switch (GetMapSettings().trail_length) { case TRAIL_OFF: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Long"), Size); break; case TRAIL_LONG: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Short"), Size); break; case TRAIL_SHORT: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Full"), Size); break; case TRAIL_FULL: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Off"), Size); break; } } if (_tcsstr(OutBuffer, _T("$(AirSpaceToggleName)"))) { ReplaceInString(OutBuffer, _T("$(AirSpaceToggleName)"), GetMapSettings().airspace.enable ? _("Off") : _("On"), Size); } if (_tcsstr(OutBuffer, _T("$(TerrainTopologyToggleName)"))) { char val = 0; if (GetMapSettings().topography_enabled) val++; if (GetMapSettings().terrain.enable) val += (char)2; switch (val) { case 0: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Topography On"), Size); break; case 1: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain On"), Size); break; case 2: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain + Topography"), Size); break; case 3: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain Off"), Size); break; } } if (_tcsstr(OutBuffer, _T("$(TerrainTopographyToggleName)"))) { char val = 0; if (GetMapSettings().topography_enabled) val++; if (GetMapSettings().terrain.enable) val += (char)2; switch (val) { case 0: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Topography On"), Size); break; case 1: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain On"), Size); break; case 2: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain + Topography"), Size); break; case 3: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain Off"), Size); break; } } CondReplaceInString(CommonInterface::main_window.GetFullScreen(), OutBuffer, _T("$(FullScreenToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().auto_zoom_enabled, OutBuffer, _T("$(ZoomAutoToggleActionName)"), _("Manual"), _("Auto"), Size); CondReplaceInString(GetMapSettings().topography_enabled, OutBuffer, _T("$(TopologyToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().topography_enabled, OutBuffer, _T("$(TopographyToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().terrain.enable, OutBuffer, _T("$(TerrainToggleActionName)"), _("Off"), _("On"), Size); if (_tcsstr(OutBuffer, _T("$(MapLabelsToggleActionName)"))) { static const TCHAR *const labels[] = { N_("All"), N_("Task & Landables"), N_("Task"), N_("None") }; static gcc_constexpr_data unsigned int n = ARRAY_SIZE(labels); unsigned int i = GetMapSettings().waypoint.label_selection; ReplaceInString(OutBuffer, _T("$(MapLabelsToggleActionName)"), gettext(labels[(i + 1) % n]), Size); } CondReplaceInString(GetComputerSettings().task.auto_mc, OutBuffer, _T("$(MacCreadyToggleActionName)"), _("Manual"), _("Auto"), Size); CondReplaceInString(GetUIState().auxiliary_enabled, OutBuffer, _T("$(AuxInfoToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetUIState().force_display_mode == DM_CIRCLING, OutBuffer, _T("$(DispModeClimbShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DM_CRUISE, OutBuffer, _T("$(DispModeCruiseShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DM_NONE, OutBuffer, _T("$(DispModeAutoShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DM_FINAL_GLIDE, OutBuffer, _T("$(DispModeFinalShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == ALLON, OutBuffer, _T("$(AirspaceModeAllShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == CLIP, OutBuffer, _T("$(AirspaceModeClipShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AUTO, OutBuffer, _T("$(AirspaceModeAutoShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == ALLBELOW, OutBuffer, _T("$(AirspaceModeBelowShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == ALLOFF, OutBuffer, _T("$(AirspaceModeAllOffIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail_length == TRAIL_OFF, OutBuffer, _T("$(SnailTrailOffShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail_length == TRAIL_SHORT, OutBuffer, _T("$(SnailTrailShortShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail_length == TRAIL_LONG, OutBuffer, _T("$(SnailTrailLongShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail_length == TRAIL_FULL, OutBuffer, _T("$(SnailTrailFullShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(!GetMapSettings().airspace.enable, OutBuffer, _T("$(AirSpaceOffShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.enable, OutBuffer, _T("$(AirSpaceOnShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(CommonInterface::GetUISettings().enable_flarm_gauge, OutBuffer, _T("$(FlarmDispToggleActionName)"), _("Off"), _("On"), Size); if (_tcsstr(OutBuffer, _T("$(NextPageName)"))) { TCHAR label[30]; const PageSettings::PageLayout &page = CommonInterface::GetUISettings().pages.pages[Pages::NextIndex()]; page.MakeTitle(label, true); ReplaceInString(OutBuffer, _T("$(NextPageName)"), label, Size); } return invalid; }
/** * Renders all the components of the moving map * @param canvas The drawing canvas * @param rc The area to draw in */ void MapWindow::Render(Canvas &canvas, const RECT &rc) { // Calculate screen positions RenderStart(canvas, rc); // Render terrain, groundline and topology and reset pen, brush and font RenderMapLayer(canvas); if (thread_generation != ui_generation) return; /* cancel */ // Render the AAT areas and airspace RenderAreas(canvas, rc); if (thread_generation != ui_generation) return; /* cancel */ // Render the snail trail /// @todo trail should be drawn above task shaded sections RenderTrail(canvas); DrawThermalEstimate(canvas); // Render task, waypoints and marks RenderTaskElements(canvas, rc); if (thread_generation != ui_generation) return; /* cancel */ // Render topology on top of airspace, to keep the text readable if (topology != NULL && SettingsMap().EnableTopology) topology->DrawLabels(canvas, projection, label_block, SettingsMap()); // Render glide through terrain range RenderGlide(canvas, rc); if (thread_generation != ui_generation) return; /* cancel */ // Render weather/terrain max/min values canvas.select(Fonts::Title); m_background.DrawSpotHeights(canvas, projection, label_block); // Render lower symbology RenderSymbology_lower(canvas, rc); // Render aircraft symbol (and FLARM traffic) RenderAirborne(canvas, rc); // Render upper symbology RenderSymbology_upper(canvas, rc); #ifdef DRAWLOAD canvas.select(Fonts::Map); TCHAR load[80]; _stprintf(load, _T("draw %d gps %d idle %d"), GetAverageTime(), Calculated().time_process_gps, Calculated().time_process_idle); canvas.text(rc.left, rc.top, load); #endif }
void GaugeVario::OnPaintBuffer(Canvas &canvas) { const PixelRect rc = GetClientRect(); const UPixelScalar width = rc.right - rc.left; const UPixelScalar height = rc.bottom - rc.top; if (!IsPersistent() || !layout_initialised) { UPixelScalar value_height = 4 + look.value_font->GetCapitalHeight() + look.text_font->GetCapitalHeight(); middle_position.y = yoffset - value_height / 2; middle_position.x = rc.right; top_position.y = middle_position.y - value_height; top_position.x = rc.right; bottom_position.y = middle_position.y + value_height; bottom_position.x = rc.right; canvas.Stretch(rc.left, rc.top, width, height, look.background_bitmap, look.background_x, 0, 58, 120); layout_initialised = true; } if (Settings().show_average) { // JMW averager now displays netto average if not circling if (!Calculated().circling) { RenderValue(canvas, top_position.x, top_position.y, &value_top, &label_top, Units::ToUserVSpeed(Calculated().netto_average), _T("NetAvg")); } else { RenderValue(canvas, top_position.x, top_position.y, &value_top, &label_top, Units::ToUserVSpeed(Calculated().average), _T("Avg")); } } if (Settings().show_mc) { fixed mc = Units::ToUserVSpeed(GetGlidePolar().GetMC()); RenderValue(canvas, bottom_position.x, bottom_position.y, &value_bottom, &label_bottom, mc, GetComputerSettings().task.auto_mc ? _T("Auto MC") : _T("MC")); } if (Settings().show_speed_to_fly) RenderSpeedToFly(canvas, rc.right - 11, (rc.top + rc.bottom) / 2); else RenderClimb(canvas); if (Settings().show_ballast) RenderBallast(canvas); if (Settings().show_bugs) RenderBugs(canvas); dirty = false; int ival, sval, ival_av = 0; static int vval_last = 0; static int sval_last = 0; static int ival_last = 0; fixed vval = Basic().brutto_vario; ival = ValueToNeedlePos(fixed(vval)); sval = ValueToNeedlePos(Calculated().sink_rate); if (Settings().show_average_needle) { if (!Calculated().circling) ival_av = ValueToNeedlePos(Calculated().netto_average); else ival_av = ValueToNeedlePos(Calculated().average); } // clear items first if (Settings().show_average_needle) { if (!IsPersistent() || ival_av != ival_last) RenderNeedle(canvas, ival_last, true, true); ival_last = ival_av; } if (!IsPersistent() || (sval != sval_last) || (ival != vval_last)) RenderVarioLine(canvas, vval_last, sval_last, true); sval_last = sval; if (!IsPersistent() || ival != vval_last) RenderNeedle(canvas, vval_last, false, true); vval_last = ival; // now draw items RenderVarioLine(canvas, ival, sval, false); if (Settings().show_average_needle) RenderNeedle(canvas, ival_av, true, false); RenderNeedle(canvas, ival, false, false); if (Settings().show_gross) { fixed vvaldisplay = Clamp(Units::ToUserVSpeed(vval), fixed(-99.9), fixed(99.9)); RenderValue(canvas, middle_position.x, middle_position.y, &value_middle, &label_middle, vvaldisplay, _T("Gross")); } RenderZero(canvas); }
void MapWindow::Render(Canvas &canvas, const PixelRect &rc) { render_projection = visible_projection; // Calculate screen position of the aircraft const RasterPoint aircraft_pos = render_projection.GeoToScreen(Basic().Location); // reset label over-write preventer label_block.reset(); // Render terrain, groundline and topography RenderTerrain(canvas); RenderTopography(canvas); RenderFinalGlideShading(canvas); // Render track bearing (ground track) DrawTrackBearing(canvas, aircraft_pos); // Render airspace RenderAirspace(canvas); // Render task, waypoints DrawTask(canvas); DrawWaypoints(canvas); // Render weather/terrain max/min values if (!m_background.DrawSpotHeights(canvas, label_block)) DrawTaskOffTrackIndicator(canvas); // Render the snail trail RenderTrail(canvas, aircraft_pos); RenderMarks(canvas); // Render estimate of thermal location DrawThermalEstimate(canvas); // Render topography on top of airspace, to keep the text readable RenderTopographyLabels(canvas); // Render glide through terrain range RenderGlide(canvas); DrawBestCruiseTrack(canvas, aircraft_pos); DrawAirspaceIntersections(canvas); // Draw wind vector at aircraft DrawWind(canvas, aircraft_pos, rc); // Draw traffic DrawTeammate(canvas); DrawFLARMTraffic(canvas, aircraft_pos); // Finally, draw you! if (Basic().Connected) Graphics::DrawAircraft(canvas, settings_map, Calculated().Heading - render_projection.GetScreenAngle(), aircraft_pos); // Render compass DrawCompass(canvas, rc); }
void InfoBoxFormatter::AssignValue(int i) { switch (i) { case 0: Value = ALTITUDEMODIFY*Basic().Altitude; break; case 1: Value = ALTITUDEMODIFY*Calculated().AltitudeAGL ; Valid = Calculated().TerrainValid; break; case 2: Value = LIFTMODIFY*Calculated().Average30s; break; case 3: Value = Calculated().WaypointBearing; Valid = Calculated().WaypointDistance > 10.0; break; case 4: if (Calculated().LD== 999) { Valid = false; } else { Valid = true; Value = Calculated().LD; } break; case 5: if (Calculated().CruiseLD== 999) { Valid = false; } else { Valid = true; Value = Calculated().CruiseLD; } break; case 6: Value = SPEEDMODIFY*Basic().Speed; break; case 7: Value = LIFTMODIFY*Calculated().LastThermalAverage; break; case 8: Value = ALTITUDEMODIFY*Calculated().LastThermalGain; break; case 10: Value = iround(LIFTMODIFY*GlidePolar::GetMacCready()*10)/10.0; break; case 11: Value = DISTANCEMODIFY*Calculated().WaypointDistance; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 12: Value = ALTITUDEMODIFY*Calculated().NextAltitudeDifference; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 13: Value = ALTITUDEMODIFY*Calculated().NextAltitudeRequired; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 14: Value = 0; // Next Waypoint Text break; case 15: Value = ALTITUDEMODIFY*Calculated().TaskAltitudeDifference; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 16: Value = ALTITUDEMODIFY*Calculated().TaskAltitudeRequired; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 17: Value = TASKSPEEDMODIFY*Calculated().TaskSpeed; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 18: if (Calculated().ValidFinish) { Value = DISTANCEMODIFY*Calculated().WaypointDistance; } else { Value = DISTANCEMODIFY*Calculated().TaskDistanceToGo; } Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 19: if (Calculated().LDFinish== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); if (Calculated().ValidFinish) { Value = 0; } else { Value = Calculated().LDFinish; } } break; case 20: Value = ALTITUDEMODIFY*Calculated().TerrainAlt ; Valid = Calculated().TerrainValid; break; case 21: Value = LIFTMODIFY*Calculated().AverageThermal; break; case 22: Value = ALTITUDEMODIFY*Calculated().ThermalGain; break; case 23: Value = Basic().TrackBearing; break; case 24: if (Basic().VarioAvailable) { Value = LIFTMODIFY*Basic().Vario; } else { Value = LIFTMODIFY*Calculated().Vario; } break; case 25: Value = SPEEDMODIFY*Calculated().WindSpeed; break; case 26: Value = Calculated().WindBearing; break; case 28: Value = DISTANCEMODIFY*Calculated().AATMaxDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 29: Value = DISTANCEMODIFY*Calculated().AATMinDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 30: Value = TASKSPEEDMODIFY*Calculated().AATMaxSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 31: Value = TASKSPEEDMODIFY*Calculated().AATMinSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 32: Valid = Basic().AirspeedAvailable; Value = SPEEDMODIFY*Basic().IndicatedAirspeed; break; case 33: Valid = Basic().BaroAltitudeAvailable; Value = ALTITUDEMODIFY*Basic().BaroAltitude; break; case 34: Value = SPEEDMODIFY*Calculated().VMacCready; break; case 35: Value = Calculated().PercentCircling; break; case 37: Valid = Basic().AccelerationAvailable; Value = Basic().Gload; break; case 38: if (Calculated().LDNext== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); Value = Calculated().LDNext; } break; case 43: // Valid = Basic().AirspeedAvailable; Value = Calculated().VOpt*SPEEDMODIFY; break; case 44: // Valid = Basic().AirspeedAvailable; Value = Calculated().NettoVario*LIFTMODIFY; break; case 48: Value = Basic().OutsideAirTemperature; break; case 49: Value = Basic().RelativeHumidity; break; case 50: Value = CuSonde::maxGroundTemperature; break; case 51: Value = DISTANCEMODIFY*Calculated().AATTargetDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 52: Value = TASKSPEEDMODIFY*Calculated().AATTargetSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 53: if (Calculated().LDvario== 999) { Valid = false; } else { Valid = Basic().VarioAvailable && Basic().AirspeedAvailable; Value = Calculated().LDvario; } break; case 54: Valid = Basic().AirspeedAvailable; Value = SPEEDMODIFY*Basic().TrueAirspeed; break; case 56: // team bearing Value = Calculated().TeammateBearing; Valid = true; case 58: // team range if (SettingsComputer().TeammateCodeValid) { Value = DISTANCEMODIFY*Calculated().TeammateRange; if (Value > 100) { _tcscpy(Format, _T("%.0lf")); } else { _tcscpy(Format, _T("%.1lf")); } Valid = true; } else { Valid = false; } break; case 59: Value = TASKSPEEDMODIFY*Calculated().TaskSpeedInstantaneous; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 60: Value = DISTANCEMODIFY*Calculated().HomeDistance ; if (SettingsComputer().HomeWaypoint>=0) { Valid = way_points.verify_index(SettingsComputer().HomeWaypoint); } else { Valid = false; } break; case 61: Value = TASKSPEEDMODIFY*Calculated().TaskSpeedAchieved; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 63: if (Calculated().timeCircling>0) { Value = LIFTMODIFY*Calculated().TotalHeightClimb /Calculated().timeCircling; Valid = true; } else { Value = 0.0; Valid = false; } break; case 64: Value = LIFTMODIFY*Calculated().DistanceVario; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 65: // battery voltage #if !defined(WINDOWSPC) && !defined(HAVE_POSIX) if (!is_altair()) { Value = PDABatteryPercent; Valid = true; } else { Value = Basic().SupplyBatteryVoltage; if (Value>0.0) { Valid = true; } else { Valid = false; } } #else Value = 0.0; Valid = false; #endif break; case 66: // VENTA-ADDON added GR Final if (Calculated().GRFinish== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); if (Calculated().ValidFinish) { Value = 0; } else { Value = Calculated().GRFinish; if (Value >100 ) { _tcscpy(Format, _T("%1.0f")); } else { _tcscpy(Format, _T("%1.1f")); } } } break; case 70: // VENTA3 QFE // Valid = Basic().Altitude; Value = ALTITUDEMODIFY* (Basic().Altitude-QFEAltitudeOffset); break; case 71: if ( Calculated().AverageLD == 0) { Valid = false; } else { Valid = true; Value = Calculated().AverageLD; if (Value<0) _tcscpy(Format, _T("^^^")); else if (Value>=999) _tcscpy(Format, _T("+++")); else _tcscpy(Format, _T("%2.0f")); } break; case 72: Value = Calculated().Experimental; Valid = true; break; /* TODO feature: add extra infoboxes from Lars case 68: // distance flown if (Calculated().TaskDistanceCovered != 0) { Value = DISTANCEMODIFY*Calculated().TaskDistanceCovered; Valid = true; } else { Value = 0.0; Valid = false; } break; case 67: // termik liga points if (Calculated().TermikLigaPoints != 0) { Value = Calculated().TermikLigaPoints; Valid = true; } else { Value = 0.0; Valid = false; } break; */ default: break; }; }
void GaugeVario::RenderSpeedToFly(Canvas &canvas, PixelScalar x, PixelScalar y) { if (!Basic().airspeed_available || !Basic().total_energy_vario_available) return; static fixed last_v_diff; fixed v_diff; const UPixelScalar arrow_y_size = Layout::Scale(3); const UPixelScalar arrow_x_size = Layout::Scale(7); const PixelRect rc = GetClientRect(); PixelScalar nary = NARROWS * arrow_y_size; PixelScalar ytop = rc.top + YOFFSET + nary; // JMW PixelScalar ybottom = rc.bottom - YOFFSET - nary - Layout::FastScale(1); ytop += Layout::Scale(14); ybottom -= Layout::Scale(14); x = rc.right - 2 * arrow_x_size; // only draw speed command if flying and vario is not circling if ((Calculated().flight.flying) && (!Basic().gps.simulator || !Calculated().circling)) { v_diff = Calculated().V_stf - Basic().indicated_airspeed; v_diff = Clamp(v_diff, -DELTA_V_LIMIT, DELTA_V_LIMIT); // limit it v_diff = iround(v_diff/DELTA_V_STEP) * DELTA_V_STEP; } else v_diff = fixed(0); if (!IsPersistent() || last_v_diff != v_diff || dirty) { last_v_diff = v_diff; if (IsPersistent()) { // bottom (too slow) canvas.DrawFilledRectangle(x, ybottom + YOFFSET, x + arrow_x_size * 2 + 1, ybottom + YOFFSET + nary + arrow_y_size + Layout::FastScale(2), look.background_color); // top (too fast) canvas.DrawFilledRectangle(x, ytop - YOFFSET + 1, x + arrow_x_size * 2 +1, ytop - YOFFSET - nary + 1 - arrow_y_size - Layout::FastScale(2), look.background_color); } RenderClimb(canvas); canvas.SelectNullPen(); if (look.colors) { if (positive(v_diff)) { // too slow canvas.Select(look.sink_brush); } else { canvas.Select(look.lift_brush); } } else { if (look.inverse) canvas.SelectWhiteBrush(); else canvas.SelectBlackBrush(); } if (positive(v_diff)) { // too slow y = ybottom; y += YOFFSET; while (positive(v_diff)) { if (v_diff > DELTA_V_STEP) { canvas.Rectangle(x, y, x + arrow_x_size * 2 + 1, y + arrow_y_size - 1); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y + arrow_y_size - 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } v_diff -= DELTA_V_STEP; y += arrow_y_size; } } else if (negative(v_diff)) { // too fast y = ytop; y -= YOFFSET; while (negative(v_diff)) { if (v_diff < -DELTA_V_STEP) { canvas.Rectangle(x, y + 1, x + arrow_x_size * 2 + 1, y - arrow_y_size + 2); } else { RasterPoint arrow[3]; arrow[0].x = x; arrow[0].y = y; arrow[1].x = x + arrow_x_size; arrow[1].y = y - arrow_y_size + 1; arrow[2].x = x + 2 * arrow_x_size; arrow[2].y = y; canvas.DrawTriangleFan(arrow, 3); } v_diff += DELTA_V_STEP; y -= arrow_y_size; } } } }
/* * The VisualGlide by Paolo Ventafridda * Sort of a Stocker dynamic chart! * * VisualGlide=1 : Steady sector/circle * 2 : Moving sector/circle optional configurable, not much useful. */ void MapWindow::DrawGlideCircle(Canvas &canvas, POINT Orig, RECT rc) { unsigned tmp=0; TCHAR gtext[100]; char text[20]; // TODO size it double cruise= Calculated().AverageLD; static double maxcruise=(GlidePolar::bestld); static double mincruise=(GlidePolar::bestld/4); int i; double gunit; static int spread=0; //short rcx=rc.left+rc.right/2-IBLSCALE(20); //short rcy=rc.bottom-IBLSCALE(15); // 35 if ( cruise < 0 ) cruise = GlidePolar::bestld; if ( cruise < mincruise ) return; if ( cruise >maxcruise ) cruise=maxcruise; // Spread from static short turn=1; static short count=0; spread += (10 * turn); if ( spread <-25 || spread >25 ) turn*=-1; if ( ++count >6) count=-1; canvas.hollow_brush(); // SetBkMode(hdc,TRANSPARENT); canvas.select(MapWindowBoldFont); // 100m or 300ft scale if ( Units::GetUserAltitudeUnit() == unMeter ) gunit=100; else gunit = 91.44; for (i=1; i<9; i++) { canvas.select(MapGfx.hpVisualGlideHeavyBlack); /* * TRACKUP, NORTHUP, NORTHCIRCLE, TRACKCIRCLE, NORTHTRACK */ if (((SettingsMap().DisplayOrientation == TRACKUP) || (SettingsMap().DisplayOrientation == NORTHCIRCLE) || (SettingsMap().DisplayOrientation == TRACKCIRCLE)) && (DisplayMode != dmCircling) ) { if ( SettingsMap().VisualGlide == 1 ) { tmp = DistanceMetersToScreen(i*gunit*cruise); canvas.arc(Orig.x, Orig.y, tmp, rc, 315, 45); } else { tmp = DistanceMetersToScreen(i*gunit*cruise); canvas.arc(Orig.x, Orig.y, tmp, rc, 330 + spread, 30 + spread); } } else { tmp = DistanceMetersToScreen(i*gunit*cruise); canvas.circle(Orig.x, Orig.y, tmp); } canvas.set_text_color(turn > 0 || true ? Color(0x0,0x0,0x0) : Color(0xff,0x00,0x00)); // red if ( i==2 || i==4 || i==6 || i==8 ) { if (Units::GetUserAltitudeUnit() == unMeter) _stprintf(gtext, _T("-%dm"), i * 100); else _stprintf(gtext, _T("-%dft"), i * 300); if (count<5) canvas.text(Orig.x + 35, Orig.y - 5 - tmp, gtext); } canvas.set_text_color(turn > 0 || true ? Color(0x0,0x0,0x0) // dark grey : Color(0xff,0x00,0x00)); // red if ( i==2 || i==4 || i==6 || i==8 ) { if ( Units::GetUserDistanceUnit() == unKiloMeter ) { //sprintf(text,"%3.1f Km",i*100*cruise /1000); sprintf(text,"%3.0fkm",i*100*cruise /1000); } else if ( Units::GetUserDistanceUnit() == unNauticalMiles ) { sprintf(text,"%3.0fnm", i*100*cruise / 1852); } else if ( Units::GetUserDistanceUnit() == unStatuteMiles ) { sprintf(text,"%3.0fm", i*100*cruise / 1609); } _stprintf(gtext, _T("%S"), text); if (count<5) canvas.text(Orig.x - 100, Orig.y - 5 - tmp, gtext); } } /* if (NewMap&&OutlinedTp) oldcolor=SetTextColor(hdc, RGB(0x0,0x0,0x0)); // dark grey 0x50 else { if (turn>0||true) oldcolor=SetTextColor(hdc, RGB(0x0,0x0,0x0)); // dark grey 0x50 else oldcolor=SetTextColor(hdc, RGB(0xff,0x00,0x00)); // red } _stprintf(gtext,_T("L/D:%d"),(int)cruise); //ExtTextOut( hdc, Orig.x+30, Orig.y +20 , 0, NULL, gtext , _tcslen(gtext), NULL ); //ExtTextOut( hdc, Orig.x-30, Orig_Aircraft.y +50 , 0, NULL, gtext , _tcslen(gtext), NULL ); //ExtTextOut( hdc, (rc.left+rc.right)/2, rc.top+rc.bottom-20 , 0, NULL, gtext , _tcslen(gtext), NULL ); if (NewMap&&OutlinedTp) { ExtTextOut( hdc, rcx+2, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx+1, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx-1, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx-2, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy+1 , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy-1 , 0, NULL, gtext , _tcslen(gtext), NULL ); #ifdef PNA if (GlobalModelType == MODELTYPE_PNA_HP31X ) { ExtTextOut( hdc, rcx+3, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx-3, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy+2 , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy-2 , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy+3 , 0, NULL, gtext , _tcslen(gtext), NULL ); ExtTextOut( hdc, rcx, rcy-3 , 0, NULL, gtext , _tcslen(gtext), NULL ); } #endif SetTextColor(hdc,RGB(0xff,0xff,0xff)); } ExtTextOut( hdc, rcx, rcy , 0, NULL, gtext , _tcslen(gtext), NULL ); */ }
void MapWindow::CalculateScreenPositionsGroundline(void) { if (SettingsComputer().FinalGlideTerrain) { LonLat2Screen(Calculated().GlideFootPrint, Groundline, NUMTERRAINSWEEPS+1, 1); } }
/** * Is called by the CalculationThread and processes the received GPS data in Basic() */ bool GlideComputer::ProcessGPS(bool force) { const MoreData &basic = Basic(); DerivedInfo &calculated = SetCalculated(); const ComputerSettings &settings = GetComputerSettings(); const bool last_flying = calculated.flight.flying; if (basic.time_available) { /* use UTC offset to calculate local time */ const int utc_offset_s = settings.utc_offset.AsSeconds(); calculated.date_time_local = basic.date_time_utc.IsDatePlausible() /* known date: apply UTC offset to BrokenDateTime, which may increment/decrement date */ ? basic.date_time_utc + utc_offset_s /* unknown date: apply UTC offset only to BrokenTime, leave the BrokenDate part invalid as it was */ : BrokenDateTime(BrokenDate::Invalid(), ((const BrokenTime &)basic.date_time_utc) + utc_offset_s); } else calculated.date_time_local = BrokenDateTime::Invalid(); calculated.Expire(basic.clock); // Process basic information air_data_computer.ProcessBasic(Basic(), SetCalculated(), GetComputerSettings()); // Process basic task information task_computer.ProcessBasicTask(basic, calculated, GetComputerSettings(), force); task_computer.ProcessMoreTask(basic, calculated, GetComputerSettings()); // Check if everything is okay with the gps time and process it air_data_computer.FlightTimes(Basic(), SetCalculated(), GetComputerSettings()); TakeoffLanding(last_flying); task_computer.ProcessAutoTask(basic, calculated); // Process extended information air_data_computer.ProcessVertical(Basic(), SetCalculated(), GetComputerSettings()); stats_computer.ProcessClimbEvents(calculated); // Calculate the team code CalculateOwnTeamCode(); // Calculate the bearing and range of the teammate CalculateTeammateBearingRange(); vegavoice.Update(basic, Calculated(), GetComputerSettings().voice); // update basic trace history if (basic.time_available) { const fixed dt = trace_history_time.Update(basic.time, fixed(0.5), fixed(30)); if (positive(dt)) calculated.trace_history.append(basic); else if (negative(dt)) /* time warp */ calculated.trace_history.clear(); } // Update the ConditionMonitors ConditionMonitorsUpdate(Basic(), Calculated(), settings); return idle_clock.CheckUpdate(500); }
void MapWindow::DrawTaskOffTrackIndicator(Canvas &canvas) { if (Calculated().Circling || !Basic().gps.Connected || !SettingsMap().EnableDetourCostMarker || (task == NULL)) return; ProtectedTaskManager::Lease task_manager(*task); if (!task_manager->check_task()) return; const TaskPoint* tp = task_manager->getActiveTaskPoint(); if (!tp) return; GeoPoint target = tp->get_location_remaining(); GeoVector vec(Basic().Location, target); if ((Basic().TrackBearing - vec.Bearing).as_delta().magnitude_degrees() < fixed(10)) // insignificant error return; fixed distance_max = min(vec.Distance, render_projection.GetScreenDistanceMeters() * fixed(0.7)); // too short to bother if (distance_max < fixed(5000)) return; GeoPoint start = Basic().Location; canvas.select(Fonts::Title); canvas.set_text_color(Color::BLACK); canvas.background_transparent(); GeoPoint dloc; int ilast = 0; for (fixed d = fixed_one / 4; d <= fixed_one; d += fixed_one / 4) { dloc = FindLatitudeLongitude(start, Basic().TrackBearing, distance_max * d); fixed distance0 = Distance(start, dloc); fixed distance1 = Distance(dloc, target); fixed distance = fixed(distance0 + distance1) / vec.Distance; int idist = iround((distance - fixed_one) * 100); if ((idist != ilast) && (idist > 0) && (idist < 1000)) { TCHAR Buffer[5]; _stprintf(Buffer, _T("%d"), idist); RasterPoint sc = render_projection.GeoToScreen(dloc); RECT brect; SIZE tsize = canvas.text_size(Buffer); brect.left = sc.x - 4; brect.right = brect.left + tsize.cx + 4; brect.top = sc.y - 4; brect.bottom = brect.top + tsize.cy + 4; if (label_block.check(brect)) { canvas.text(sc.x - tsize.cx / 2, sc.y - tsize.cy / 2, Buffer); ilast = idist; } } } }
void LoanAssMatcherThread::EmitFromAnonim() { Q_D( LoanAssMatcherThread); emit Calculated(d->Identifier, d->Result); }
/** * SearchBestAlternate() beta * based on SortLandableWaypoints and extended * @author Paolo Ventafridda */ void GlideComputerTask::SearchBestAlternate() { int SortedLandableIndex[MAXBEST]; double SortedArrivalAltitude[MAXBEST]; int SortedApproxDistance[MAXBEST*2]; int SortedApproxIndex[MAXBEST*2]; int i, k, l; double arrival_altitude; int active_bestalternate_on_entry=-1; int bestalternate=-1; /* * VENTA3 search in range of optimum gliding capability * and in any case within an acceptable distance, say 100km. * Anything else is not considered, since we want a safe landing not a long glide. * Preferred waypoints and home are nevertheless checked in any case later. * Notice that if you are over 100km away from the nearest non-preferred landing point you can't * expect a computer to be helpful in case of troubles. * * ApproxDistance is in km, very approximate */ double searchrange=(Basic().Altitude- SettingsComputer().SafetyAltitudeArrival) *GlidePolar::bestld /1000; if (searchrange <= 0) searchrange=2; // lock to home airport at once if (searchrange > ALTERNATE_MAXRANGE) searchrange=ALTERNATE_MAXRANGE; active_bestalternate_on_entry = Calculated().BestAlternate; // Do preliminary fast search POINT sc_aircraft; LatLon2Flat(Basic().Location, sc_aircraft); // Clear search lists for (i=0; i<MAXBEST*2; i++) { SortedApproxIndex[i]= -1; SortedApproxDistance[i] = 0; } for (i = 0; way_points.verify_index(i); i++) { const WAYPOINT &way_point = way_points.get(i); if (!(((way_point.Flags & AIRPORT) == AIRPORT) || ((way_point.Flags & LANDPOINT) == LANDPOINT))) { continue; // ignore non-landable fields } int approx_distance = CalculateWaypointApproxDistance(sc_aircraft, way_point); // Size a reasonable distance, wide enough VENTA3 if ( approx_distance > searchrange ) continue; // see if this fits into slot for (k=0; k< MAXBEST*2; k++) { if (((approx_distance < SortedApproxDistance[k]) // wp is closer than this one || (SortedApproxIndex[k]== -1)) // or this one isn't filled && (SortedApproxIndex[k]!= i)) // and not replacing with same { // ok, got new biggest, put it into the slot. for (l=MAXBEST*2-1; l>k; l--) { if (l>0) { SortedApproxDistance[l] = SortedApproxDistance[l-1]; SortedApproxIndex[l] = SortedApproxIndex[l-1]; } } SortedApproxDistance[k] = approx_distance; SortedApproxIndex[k] = i; k=MAXBEST*2; } } // for k } // for i // Now do detailed search for (i=0; i<MAXBEST; i++) { SortedLandableIndex[i]= -1; SortedArrivalAltitude[i] = 0; } bool found_reachable_airport = false; for (int scan_airports_slot=0; scan_airports_slot<2; scan_airports_slot++) { if (found_reachable_airport ) { continue; // don't bother filling the rest of the list } for (i=0; i<MAXBEST*2; i++) { if (SortedApproxIndex[i]<0) { // ignore invalid points continue; } const WAYPOINT &way_point = way_points.get(SortedApproxIndex[i]); WPCALC &wpcalc = way_points.set_calc(SortedApproxIndex[i]); if ((scan_airports_slot==0) && ((way_point.Flags & AIRPORT) != AIRPORT)) { // we are in the first scan, looking for airports only continue; } arrival_altitude = CalculateWaypointArrivalAltitude(way_point, wpcalc); wpcalc.AltArrival = arrival_altitude; // This is holding the real arrival value /* * We can't use degraded polar here, but we can't accept an * arrival 1m over safety. That is 2m away from being * unreachable! So we higher this value to 100m. */ arrival_altitude -= ALTERNATE_OVERSAFETY; if (scan_airports_slot==0) { if (arrival_altitude<0) { // in first scan, this airport is unreachable, so ignore it. continue; } else // this airport is reachable found_reachable_airport = true; } // see if this fits into slot for (k=0; k< MAXBEST; k++) { if (((arrival_altitude > SortedArrivalAltitude[k]) // closer than this one ||(SortedLandableIndex[k]== -1)) // or this one isn't filled &&(SortedLandableIndex[k]!= i)) // and not replacing // with same { double wp_distance, wp_bearing; DistanceBearing(Basic().Location, way_point.Location, &wp_distance, &wp_bearing); wpcalc.Distance = wp_distance; wpcalc.Bearing = wp_bearing; bool out_of_range; terrain.Lock(); double distance_soarable = FinalGlideThroughTerrain(wp_bearing, Basic(), Calculated(), SettingsComputer(), terrain, NULL, wp_distance, &out_of_range, NULL); terrain.Unlock(); if ((distance_soarable>= wp_distance)||(arrival_altitude<0)) { // only put this in the index if it is reachable // and doesn't go through terrain, OR, if it is unreachable // it doesn't matter if it goes through terrain because // pilot has to climb first anyway // ok, got new biggest, put it into the slot. for (l=MAXBEST-1; l>k; l--) { if (l>0) { SortedArrivalAltitude[l] = SortedArrivalAltitude[l-1]; SortedLandableIndex[l] = SortedLandableIndex[l-1]; } } SortedArrivalAltitude[k] = arrival_altitude; SortedLandableIndex[k] = SortedApproxIndex[i]; k=MAXBEST; } } // if (((arrival_altitude > SortedArrivalAltitude[k]) ... } // for (k=0; k< MAXBEST; k++) { } } // extended part by Paolo bestalternate=-1; // reset the good choice double safecalc = Calculated().NavAltitude - SettingsComputer().SafetyAltitudeArrival; static double grpolar = GlidePolar::bestld *SAFELD_FACTOR; int curwp, curbestairport=-1, curbestoutlanding=-1; double curgr=0, curbestgr=INVALID_GR; if ( safecalc <= 0 ) { /* * We're under the absolute safety altitude at MSL, can't be any better elsewhere! * Use the closer, hopefully you are landing on your airport */ } else for (k=0; k< MAXBEST; k++) { curwp = SortedLandableIndex[k]; if ( !way_points.verify_index(curwp) ) { continue; // break; // that list is unsorted ! } const WAYPOINT &way_point = way_points.get(curwp); WPCALC &wpcalc = way_points.set_calc(SortedApproxIndex[i]); // At the first unsafe landing, stop searching down the list and // use the best found or the first double grsafe = safecalc - way_point.Altitude; if ( grsafe <= 0 ) { /* * We're under the safety altitude for this waypoint. */ break; //continue; } wpcalc.GR = wpcalc.Distance / grsafe; grsafe = wpcalc.GR; curgr = wpcalc.GR; if ( grsafe > grpolar ) { /* * Over degraded polar GR for this waypoint */ continue; // break; } // Anything now is within degraded glide ratio, so if our homewaypoint is safely reachable then // attempt to lock it even if we already have a valid best, even if it is preferred and even // if it has a better GR if ( (SettingsComputer().HomeWaypoint >= 0) && (curwp == SettingsComputer().HomeWaypoint) ) { bestalternate = curwp; break; } // If we already found a preferred, stop searching for anything but home if (bestalternate >= 0 && way_points.get_calc(bestalternate).Preferred) { continue; } // VENTA5 TODO: extend search on other preferred, choosing the closer one // Preferred list has priority, first found is taken (could be smarted) if (wpcalc.Preferred) { bestalternate=curwp; continue; } // else we remember the best landable GR found so far. We shall use this in case // at the end of the search no home and no preferred were found. if ( curgr < curbestgr ) { if ((way_point.Flags & AIRPORT) == AIRPORT) { curbestairport=curwp; curbestgr=curgr; // ONLY FOR AIRPORT! NOT FOR OUTLANDINGS!! } else { curbestoutlanding=curwp; } } continue; } if ( bestalternate <0 ) { if ( curbestairport >= 0 ) { bestalternate=curbestairport; } else { if ( curbestoutlanding >= 0 ) { bestalternate=curbestoutlanding; } else { /* * Here we are in troubles, nothing really reachable, but we * might still be lucky to be within the "yellow" glide * path. In any case we select the best arrival altitude place * available, even if it is "red". */ if ( way_points.verify_index(SortedLandableIndex[0]) ) { bestalternate=SortedLandableIndex[0]; } else { /* * Else the Landable list is EMPTY, although we might be * near to a landable point but the terrain obstacles look * too high (or the DEM resolution is not high enough to * show a passage). * * Still the old BestAlternate could simply be out of range, * but reachable... These values have certainly just been * calculated by DoAlternates() , so they are usable. */ // Attempt to use the old best, but check there's one.. it // might be empty for the first run if ( way_points.verify_index(active_bestalternate_on_entry) ) { bestalternate=active_bestalternate_on_entry; if (way_points.get_calc(bestalternate).AltArrival < 0) { // Pick up the closest! if ( way_points.verify_index( SortedApproxIndex[0]) ) { bestalternate=SortedApproxIndex[0]; } else { // CRITIC POINT // Otherwise .. nothing, either keep the old best or // set it empty // Put here "PULL-UP! PULL-UP! Boeing // cockpit voice sound and possibly shake the stick. } } else { // MapWindow2 is checking for reachables separately, // se let's see if this closest is reachable if ( way_points.verify_index( SortedApproxIndex[0] )) { if (way_points.get_calc(SortedApproxIndex[0]).Reachable) { bestalternate = SortedApproxIndex[0]; } else { } } else { } } } else { // CRITIC POINT } } /* * Don't make any sound at low altitudes, pilot is either taking off * or landing, or searching for an immediate outlanding. Do not disturb. * If safetyaltitude is 300m, then below 500m be quiet. * If there was no active alternate on entry, and nothing was found, then we * better be quiet since probably the user had already been alerted previously * and now he is low.. */ if ( bestalternate >0 && ((safecalc - way_points.get(bestalternate).Altitude) > ALTERNATE_QUIETMARGIN)) { if (way_points.get_calc(bestalternate).AltArrivalAGL <100 ) AlertBestAlternate(2); // if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_RED")); } } } } /* * If still invalid, it should mean we are just taking off * in this case no problems, we set the very first bestalternate of the day as the home * trusting the user to be home really! */ if ( bestalternate < 0 ) { if ( SettingsComputer().HomeWaypoint >= 0 ) { bestalternate=SettingsComputer().HomeWaypoint; } } else { // If still invalid, i.e. not -1, then there's a big problem if ( !way_points.verify_index(bestalternate) ) { AlertBestAlternate(2); Message::AddMessage(_T("Error, invalid best alternate!")); // todo: immediate disable function } } if (active_bestalternate_on_entry != bestalternate) { SetCalculated().BestAlternate = bestalternate; if ( bestalternate >0 && ((safecalc - way_points.get(bestalternate).Altitude) > ALTERNATE_QUIETMARGIN)) AlertBestAlternate(1); } }
/** * Draw the final glide groundline (and shading) to the buffer * and copy the transparent buffer to the canvas * @param canvas The drawing canvas * @param rc The area to draw in * @param buffer The drawing buffer */ void MapWindow::DrawTerrainAbove(Canvas &canvas) { // Don't draw at all if // .. no GPS fix // .. not flying // .. feature disabled // .. feature inaccessible if (!Basic().location_available || !Calculated().flight.flying || GetComputerSettings().features.final_glide_terrain == FeaturesSettings::FinalGlideTerrain::OFF || route_planner == nullptr) return; // Create a visitor for the Reach code TriangleCompound visitor(render_projection); // Fill the TriangleCompound with all TriangleFans in range route_planner->AcceptInRange(render_projection.GetScreenBounds(), visitor); // Exit early if not fans found if (visitor.fans.empty()) return; // @todo: update this rendering // Don't draw shade if // .. shade feature disabled // .. pan mode activated if (GetComputerSettings().features.final_glide_terrain == FeaturesSettings::FinalGlideTerrain::SHADE && IsNearSelf()) { #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); const GLEnable stencil_test(GL_STENCIL_TEST); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); COLOR_WHITE.Set(); visitor.fans.DrawFill(canvas); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); const GLBlend blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); canvas.Clear(Color(255, 255, 255, 77)); #elif defined(USE_GDI) // Get a buffer for drawing a mask Canvas &buffer = buffer_canvas; // Set the pattern colors buffer.SetBackgroundOpaque(); buffer.SetBackgroundColor(COLOR_WHITE); buffer.SetTextColor(Color(0xd0, 0xd0, 0xd0)); // Paint the whole buffer canvas with a pattern brush (small dots) buffer.Clear(look.above_terrain_brush); // Select the TerrainLine pen buffer.SelectHollowBrush(); buffer.Select(look.reach_pen_thick); buffer.SetBackgroundColor(Color(0xf0, 0xf0, 0xf0)); // Draw the TerrainLine polygons visitor.fans.DrawOutline(buffer); // Select a white brush (will later be transparent) buffer.SelectNullPen(); buffer.SelectWhiteBrush(); // Draw the TerrainLine polygons to remove the // brush pattern from the polygon areas visitor.fans.DrawFill(buffer); // Copy everything non-white to the buffer canvas.CopyTransparentWhite(0, 0, render_projection.GetScreenWidth(), render_projection.GetScreenHeight(), buffer, 0, 0); /* skip the separate terrain line step below, because we have done it already */ return; #endif } if (visitor.fans.size() == 1) { /* only one fan: we can draw a simple polygon */ #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); look.reach_pen.Bind(); #else // Select the TerrainLine pen canvas.SelectHollowBrush(); canvas.Select(look.reach_pen); canvas.SetBackgroundOpaque(); canvas.SetBackgroundColor(COLOR_WHITE); // drop out extraneous line from origin #endif // Draw the TerrainLine polygon visitor.fans.DrawOutline(canvas); #ifdef ENABLE_OPENGL look.reach_pen.Unbind(); #endif } else { /* more than one fan (turning reach enabled): we have to use a stencil to draw the outline, because the fans may overlap */ #ifdef ENABLE_OPENGL const ScopeVertexPointer vp(&visitor.fans.points[0]); glEnable(GL_STENCIL_TEST); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); COLOR_WHITE.Set(); visitor.fans.DrawFill(canvas); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); look.reach_pen_thick.Bind(); visitor.fans.DrawOutline(canvas); look.reach_pen_thick.Unbind(); glDisable(GL_STENCIL_TEST); #elif defined(USE_GDI) || defined(USE_MEMORY_CANVAS) // Get a buffer for drawing a mask Canvas &buffer = buffer_canvas; // Paint the whole buffer canvas white ( = transparent) buffer.ClearWhite(); // Select the TerrainLine pen buffer.SelectHollowBrush(); buffer.Select(look.reach_pen_thick); buffer.SetBackgroundOpaque(); buffer.SetBackgroundColor(Color(0xf0, 0xf0, 0xf0)); // Draw the TerrainLine polygons visitor.fans.DrawOutline(buffer); // Select a white brush (will later be transparent) buffer.SelectNullPen(); buffer.SelectWhiteBrush(); // Draw the TerrainLine polygons again to remove // the lines connecting all the polygons // // This removes half of the TerrainLine line width !! visitor.fans.DrawFill(buffer); // Copy everything non-white to the buffer canvas.CopyTransparentWhite(0, 0, render_projection.GetScreenWidth(), render_projection.GetScreenHeight(), buffer, 0, 0); #endif } }
bool ButtonLabel::ExpandMacros(const TCHAR *In, TCHAR *OutBuffer, size_t Size) { // ToDo, check Buffer Size bool invalid = false; _tcsncpy(OutBuffer, In, Size); OutBuffer[Size-1] = '\0'; if (_tcsstr(OutBuffer, TEXT("$(")) == NULL) return false; if (task.isTaskAborted()) { if (_tcsstr(OutBuffer, TEXT("$(WaypointNext)"))) { // Waypoint\nNext invalid = !task.ValidTaskPoint(task.getActiveIndex()+1); CondReplaceInString(!task.ValidTaskPoint(task.getActiveIndex()+2), OutBuffer, TEXT("$(WaypointNext)"), TEXT("Landpoint\nFurthest"), TEXT("Landpoint\nNext"), Size); } else if (_tcsstr(OutBuffer, TEXT("$(WaypointPrevious)"))) { // Waypoint\nNext invalid = !task.ValidTaskPoint(task.getActiveIndex()-1); CondReplaceInString(!task.ValidTaskPoint(task.getActiveIndex()-2), OutBuffer, TEXT("$(WaypointPrevious)"), TEXT("Landpoint\nClosest"), TEXT("Landpoint\nPrevious"), Size); } } else { if (_tcsstr(OutBuffer, TEXT("$(WaypointNext)"))) { // Waypoint\nNext invalid = !task.ValidTaskPoint(task.getActiveIndex()+1); CondReplaceInString(!task.ValidTaskPoint(task.getActiveIndex()+2), OutBuffer, TEXT("$(WaypointNext)"), TEXT("Waypoint\nFinish"), TEXT("Waypoint\nNext"), Size); } else if (_tcsstr(OutBuffer, TEXT("$(WaypointPrevious)"))) { if (task.getActiveIndex()==1) { invalid = !task.ValidTaskPoint(task.getActiveIndex()-1); ReplaceInString(OutBuffer, TEXT("$(WaypointPrevious)"), TEXT("Waypoint\nStart"), Size); } else if (task.getSettings().EnableMultipleStartPoints) { invalid = !task.ValidTaskPoint(0); CondReplaceInString((task.getActiveIndex()==0), OutBuffer, TEXT("$(WaypointPrevious)"), TEXT("StartPoint\nCycle"), TEXT("Waypoint\nPrevious"), Size); } else { invalid = (task.getActiveIndex()<=0); ReplaceInString(OutBuffer, TEXT("$(WaypointPrevious)"), TEXT("Waypoint\nPrevious"), Size); } } } if (_tcsstr(OutBuffer, TEXT("$(AdvanceArmed)"))) { switch (task.getSettings().AutoAdvance) { case 0: ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("(manual)"), Size); invalid = true; break; case 1: ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("(auto)"), Size); invalid = true; break; case 2: if (task.getActiveIndex()>0) { if (task.ValidTaskPoint(task.getActiveIndex()+1)) { CondReplaceInString(task.isAdvanceArmed(), OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("Cancel"), TEXT("TURN"), Size); } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("(finish)"), Size); invalid = true; } } else { CondReplaceInString(task.isAdvanceArmed(), OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("Cancel"), TEXT("START"), Size); } break; case 3: if (task.getActiveIndex()==0) { CondReplaceInString(task.isAdvanceArmed(), OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("Cancel"), TEXT("START"), Size); } else if (task.getActiveIndex()==1) { CondReplaceInString(task.isAdvanceArmed(), OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("Cancel"), TEXT("RESTART"), Size); } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), TEXT("(auto)"), Size); invalid = true; } // TODO bug: no need to arm finish default: break; } } if (_tcsstr(OutBuffer, TEXT("$(CheckReplay)"))) { if (!Basic().Replay && Basic().MovementDetected) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckReplay)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckWaypointFile)"))) { if (!way_points.verify_index(0)) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckWaypointFile)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckSettingsLockout)"))) { if (!is_simulator() && XCSoarInterface::LockSettingsInFlight && Calculated().Flying) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckSettingsLockout)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckTaskResumed)"))) { if (task.isTaskAborted()) { // TODO code: check, does this need to be set with temporary task? invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckTaskResumed)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckTask)"))) { if (!task.Valid()) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckTask)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckAirspace)"))) { if (!ValidAirspace()) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckAirspace)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckFLARM)"))) { if (!Basic().FLARM_Available) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckFLARM)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckTerrain)"))) { if (!Calculated().TerrainValid) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckTerrain)"), TEXT(""), Size); } if (_tcsstr(OutBuffer, TEXT("$(CheckAutoMc)"))) { if (!task.Valid() && ((SettingsComputer().AutoMcMode==0) || (SettingsComputer().AutoMcMode==2))) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckAutoMc)"), TEXT(""), Size); } CondReplaceInString(logger.isLoggerActive(), OutBuffer, TEXT("$(LoggerActive)"), TEXT("Stop"), TEXT("Start"), Size); if (_tcsstr(OutBuffer, TEXT("$(SnailTrailToggleName)"))) { switch(SettingsMap().TrailActive) { case 0: ReplaceInString(OutBuffer, TEXT("$(SnailTrailToggleName)"), TEXT("Long"), Size); break; case 1: ReplaceInString(OutBuffer, TEXT("$(SnailTrailToggleName)"), TEXT("Short"), Size); break; case 2: ReplaceInString(OutBuffer, TEXT("$(SnailTrailToggleName)"), TEXT("Full"), Size); break; case 3: ReplaceInString(OutBuffer, TEXT("$(SnailTrailToggleName)"), TEXT("Off"), Size); break; } } // VENTA3 VisualGlide if (_tcsstr(OutBuffer, TEXT("$(VisualGlideToggleName)"))) { switch(SettingsMap().VisualGlide) { case 0: ReplaceInString(OutBuffer, TEXT("$(VisualGlideToggleName)"), TEXT("Steady"), Size); break; case 1: if (SettingsMap().ExtendedVisualGlide) ReplaceInString(OutBuffer, TEXT("$(VisualGlideToggleName)"), TEXT("Moving"), Size); else ReplaceInString(OutBuffer, TEXT("$(VisualGlideToggleName)"), TEXT("Off"), Size); break; case 2: ReplaceInString(OutBuffer, TEXT("$(VisualGlideToggleName)"), TEXT("Off"), Size); break; } } // VENTA3 AirSpace event if (_tcsstr(OutBuffer, TEXT("$(AirSpaceToggleName)"))) { switch(SettingsMap().OnAirSpace) { case 0: ReplaceInString(OutBuffer, TEXT("$(AirSpaceToggleName)"), TEXT("ON"), Size); break; case 1: ReplaceInString(OutBuffer, TEXT("$(AirSpaceToggleName)"), TEXT("OFF"), Size); break; } } if (_tcsstr(OutBuffer, TEXT("$(TerrainTopologyToggleName)"))) { char val; val = 0; if (SettingsMap().EnableTopology) val++; if (SettingsMap().EnableTerrain) val += (char)2; switch(val) { case 0: ReplaceInString(OutBuffer, TEXT("$(TerrainTopologyToggleName)"), TEXT("Topology\nOn"), Size); break; case 1: ReplaceInString(OutBuffer, TEXT("$(TerrainTopologyToggleName)"), TEXT("Terrain\nOn"), Size); break; case 2: ReplaceInString(OutBuffer, TEXT("$(TerrainTopologyToggleName)"), TEXT("Terrain\nTopology"), Size); break; case 3: ReplaceInString(OutBuffer, TEXT("$(TerrainTopologyToggleName)"), gettext(TEXT("Terrain\nOff")), Size); break; } } ////// CondReplaceInString(task.TaskIsTemporary(), OutBuffer, TEXT("$(TaskAbortToggleActionName)"), TEXT("Resume"), TEXT("Abort"), Size); CondReplaceInString(SettingsMap().FullScreen, OutBuffer, TEXT("$(FullScreenToggleActionName)"), TEXT("Off"), TEXT("On"), Size); CondReplaceInString(SettingsMap().AutoZoom, OutBuffer, TEXT("$(ZoomAutoToggleActionName)"), TEXT("Manual"), TEXT("Auto"), Size); CondReplaceInString(SettingsMap().EnableTopology, OutBuffer, TEXT("$(TopologyToggleActionName)"), TEXT("Off"), TEXT("On"), Size); CondReplaceInString(SettingsMap().EnableTerrain, OutBuffer, TEXT("$(TerrainToggleActionName)"), TEXT("Off"), TEXT("On"), Size); if (_tcsstr(OutBuffer, TEXT("$(MapLabelsToggleActionName)"))) { switch(SettingsMap().DeclutterLabels) { case 0: ReplaceInString(OutBuffer, TEXT("$(MapLabelsToggleActionName)"), TEXT("MID"), Size); break; case 1: ReplaceInString(OutBuffer, TEXT("$(MapLabelsToggleActionName)"), TEXT("OFF"), Size); break; case 2: ReplaceInString(OutBuffer, TEXT("$(MapLabelsToggleActionName)"), TEXT("ON"), Size); break; } } CondReplaceInString(SettingsComputer().AutoMacCready != 0, OutBuffer, TEXT("$(MacCreadyToggleActionName)"), TEXT("Manual"), TEXT("Auto"), Size); CondReplaceInString(SettingsMap().EnableAuxiliaryInfo, OutBuffer, TEXT("$(AuxInfoToggleActionName)"), TEXT("Off"), TEXT("On"), Size); CondReplaceInString(SettingsMap().UserForceDisplayMode == dmCircling, OutBuffer, TEXT("$(DispModeClimbShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().UserForceDisplayMode == dmCruise, OutBuffer, TEXT("$(DispModeCruiseShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().UserForceDisplayMode == dmNone, OutBuffer, TEXT("$(DispModeAutoShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().UserForceDisplayMode == dmFinalGlide, OutBuffer, TEXT("$(DispModeFinalShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsComputer().AltitudeMode == ALLON, OutBuffer, TEXT("$(AirspaceModeAllShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsComputer().AltitudeMode == CLIP, OutBuffer, TEXT("$(AirspaceModeClipShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsComputer().AltitudeMode == AUTO, OutBuffer, TEXT("$(AirspaceModeAutoShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsComputer().AltitudeMode == ALLBELOW, OutBuffer, TEXT("$(AirspaceModeBelowShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsComputer().AltitudeMode == ALLOFF, OutBuffer, TEXT("$(AirspaceModeAllOffIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().TrailActive == 0, OutBuffer, TEXT("$(SnailTrailOffShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().TrailActive == 2, OutBuffer, TEXT("$(SnailTrailShortShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().TrailActive == 1, OutBuffer, TEXT("$(SnailTrailLongShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().TrailActive == 3, OutBuffer, TEXT("$(SnailTrailFullShortIndicator)"), TEXT("(*)"), TEXT(""), Size); // VENTA3 VisualGlide CondReplaceInString(SettingsMap().VisualGlide == 0, OutBuffer, TEXT("$(VisualGlideOffShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().VisualGlide == 1, OutBuffer, TEXT("$(VisualGlideLightShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().VisualGlide == 2, OutBuffer, TEXT("$(VisualGlideHeavyShortIndicator)"), TEXT("(*)"), TEXT(""), Size); // VENTA3 AirSpace CondReplaceInString(SettingsMap().OnAirSpace == 0, OutBuffer, TEXT("$(AirSpaceOffShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().OnAirSpace == 1, OutBuffer, TEXT("$(AirSpaceOnShortIndicator)"), TEXT("(*)"), TEXT(""), Size); CondReplaceInString(SettingsMap().EnableFLARMGauge != 0, OutBuffer, TEXT("$(FlarmDispToggleActionName)"), TEXT("Off"), TEXT("On"), Size); return invalid; }
void MapWindow::CalculateScreenPositionsGroundline(void) { if (SettingsComputer().FinalGlideTerrain) for (unsigned i = 0; i < TERRAIN_ALT_INFO::NUMTERRAINSWEEPS; ++i) Groundline[i] = render_projection.GeoToScreen(Calculated().GlideFootPrint[i]); }