/** * Check whether this intersection should be added to, or updated in, the warning manager * * @param airspace Airspace corresponding to current intersection */ void Intersection(const AbstractAirspace& airspace) { if (!airspace.IsActive()) return; // ignore inactive airspaces completely if (!warning_manager.GetConfig().IsClassEnabled(airspace.GetType()) || ExcludeAltitude(airspace)) return; AirspaceWarning *warning = warning_manager.GetWarningPtr(airspace); if (warning == NULL || warning->IsStateAccepted(warning_state)) { AirspaceInterceptSolution solution; if (mode_inside) { airspace.Intercept(state, perf, solution, state.location, state.location); } else { solution = Intercept(airspace, state, perf); } if (!solution.IsValid()) return; if (solution.elapsed_time > max_time) return; if (warning == NULL) warning = warning_manager.GetNewWarningPtr(airspace); warning->UpdateSolution(warning_state, solution); found = true; } }
virtual void Visit(const AirspaceWarning& as) { if (as.get_warning_state() == m_state) { #ifdef DO_PRINT *fout << as; *fout << as.get_airspace(); #endif } }
bool AirspaceWarning::operator<(const AirspaceWarning &other) const { // compare bother.ack if (get_ack_expired() != other.get_ack_expired()) // least expired top return get_ack_expired() > other.get_ack_expired(); // compare bother.state if (get_warning_state() != other.get_warning_state()) // most severe top return get_warning_state() > other.get_warning_state(); // state and ack equal, compare bother.time to intersect return get_solution().elapsed_time < other.get_solution().elapsed_time; }
bool AirspaceWarning::operator<(const AirspaceWarning &other) const { // compare bother.ack if (IsAckExpired() != other.IsAckExpired()) // least expired top return IsAckExpired() > other.IsAckExpired(); // compare bother.state if (GetWarningState() != other.GetWarningState()) // most severe top return GetWarningState() > other.GetWarningState(); // state and ack equal, compare bother.time to intersect return GetSolution().elapsed_time < other.GetSolution().elapsed_time; }
static void Enable() { const AbstractAirspace *airspace = GetSelectedAirspace(); if (airspace == NULL) return; { ProtectedAirspaceWarningManager::ExclusiveLease lease(*airspace_warnings); AirspaceWarning *warning = lease->GetWarningPtr(*airspace); if (warning == NULL) return; warning->AcknowledgeInside(false); warning->AcknowledgeWarning(false); warning->AcknowledgeDay(false); } UpdateList(); }
bool AirspaceWarningManager::UpdateInside(const AircraftState& state, const GlidePolar &glide_polar) { if (!glide_polar.IsValid()) return false; bool found = false; AirspacePredicateAircraftInside condition(state); Airspaces::AirspaceVector results = airspaces.FindInside(state, condition); for (const auto &i : results) { const AbstractAirspace &airspace = i.GetAirspace(); if (!airspace.IsActive()) continue; // ignore inactive airspaces if (!config.IsClassEnabled(airspace.GetType())) continue; AirspaceWarning *warning = GetWarningPtr(airspace); if (warning == nullptr || warning->IsStateAccepted(AirspaceWarning::WARNING_INSIDE)) { GeoPoint c = airspace.ClosestPoint(state.location, GetProjection()); const AirspaceAircraftPerformance perf_glide(glide_polar); AirspaceInterceptSolution solution; airspace.Intercept(state, c, GetProjection(), perf_glide, solution); if (warning == nullptr) warning = GetNewWarningPtr(airspace); warning->UpdateSolution(AirspaceWarning::WARNING_INSIDE, solution); found = true; } } return found; }
void Visit(const AirspaceWarning& as) { if (as.GetWarningState() == AirspaceWarning::WARNING_INSIDE) { ids_inside.checked_append(&as.GetAirspace()); } else if (as.GetWarningState() > AirspaceWarning::WARNING_CLEAR) { ids_warning.checked_append(&as.GetAirspace()); locations.checked_append(as.GetSolution().location); } if (!as.IsAckExpired()) ids_acked.checked_append(&as.GetAirspace()); }
void Visit(const AirspaceWarning& as) { if (as.get_warning_state()== AirspaceWarning::WARNING_INSIDE) { ids_inside.checked_append(&as.get_airspace()); } else if (as.get_warning_state()> AirspaceWarning::WARNING_CLEAR) { ids_warning.checked_append(&as.get_airspace()); locs.checked_append(as.get_solution().location); } if (!as.get_ack_expired()) { ids_acked.checked_append(&as.get_airspace()); } }
void Add(const AirspaceWarning& as) { if (as.GetWarningState() > AirspaceWarning::WARNING_CLEAR) list.checked_append(&as.GetAirspace()); }
static void OnAirspaceListItemPaint(Canvas &canvas, const PixelRect paint_rc, unsigned i) { TCHAR sTmp[128]; const int paint_rc_margin = 2; ///< This constant defines the margin that should be respected for renderring within the paint_rc area. bool ack1_vis; bool ack2_vis; bool ack_vis; bool enable_vis; bool update_vis = false; { ProtectedAirspaceWarningManager::Lease lease(*airspace_warnings); if (lease->empty()) { // the warnings were emptied between the opening of the dialog // and this refresh, so only need to display "No Warnings" for // top item, otherwise exit immediately if (i==0) { canvas.text(paint_rc.left + IBLSCALE(paint_rc_margin), paint_rc.top + IBLSCALE(paint_rc_margin), _("No Warnings")); } return; } if (i >= lease->size()) /* this cannot be an assertion, because another thread may have modified the AirspaceWarningManager */ return; const AirspaceWarning warning = *(lease->get_warning(i)); const AbstractAirspace& as = warning.get_airspace(); const AirspaceInterceptSolution& solution = warning.get_solution(); tstring sName = as.get_name_text(false); tstring sTop = as.get_top_text(true); tstring sBase = as.get_base_text(true); tstring sType = as.get_type_text(true); const int TextHeight = 12, TextTop = 1; const int statusColWidth = canvas.text_width(_T("inside")); //<-- word "inside" is used as the etalon, because it is longer than "near" and currently (9.4.2011) there is no other possibility for the status text. const int heightColWidth = canvas.text_width(_T("1888 m AGL")); // <-- "1888" is used in order to have enough space for 4-digit heights with "AGL" /// Dynamic columns scaling - "name" column is flexible, altitude and state columns are fixed-width. const int Col0LeftScreenCoords = Layout::FastScale(paint_rc_margin), Col2LeftScreenCoords = paint_rc.right - Layout::FastScale(paint_rc_margin) - (statusColWidth + 2 * Layout::FastScale(paint_rc_margin)), Col1LeftScreenCoords = Col2LeftScreenCoords - Layout::FastScale(paint_rc_margin) - heightColWidth; PixelRect rcTextClip; rcTextClip = paint_rc; rcTextClip.right = Col1LeftScreenCoords - Layout::FastScale(paint_rc_margin); Color old_text_color = canvas.get_text_color(); if (!warning.get_ack_expired()) canvas.set_text_color(COLOR_GRAY); { // name, altitude info _stprintf(sTmp, _T("%-20s"), sName.c_str()); canvas.text_clipped(paint_rc.left + Col0LeftScreenCoords, paint_rc.top + IBLSCALE(TextTop), rcTextClip, sTmp); _stprintf(sTmp, _T("%-20s"), sTop.c_str()); canvas.text(paint_rc.left + Col1LeftScreenCoords, paint_rc.top + IBLSCALE(TextTop), sTmp); _stprintf(sTmp, _T("%-20s"), sBase.c_str()); canvas.text(paint_rc.left + Col1LeftScreenCoords, paint_rc.top + IBLSCALE(TextTop + TextHeight), sTmp); } if (warning.get_warning_state() != AirspaceWarning::WARNING_INSIDE && warning.get_warning_state() > AirspaceWarning::WARNING_CLEAR) { _stprintf(sTmp, _T("%d secs dist %d m"), (int)solution.elapsed_time, (int)solution.distance); canvas.text_clipped(paint_rc.left + Col0LeftScreenCoords, paint_rc.top + IBLSCALE(TextTop + TextHeight), rcTextClip, sTmp); } /* draw the warning state indicator */ Brush *state_brush; const TCHAR *state_text; if (warning.get_warning_state() == AirspaceWarning::WARNING_INSIDE) { if (warning.get_ack_expired()) state_brush = &hBrushInsideBk; else state_brush = &hBrushInsideAckBk; state_text = _T("inside"); } else if (warning.get_warning_state() > AirspaceWarning::WARNING_CLEAR) { if (warning.get_ack_expired()) state_brush = &hBrushNearBk; else state_brush = &hBrushNearAckBk; state_text = _T("near"); } else { state_brush = NULL; state_text = NULL; } const PixelSize state_text_size = canvas.text_size(state_text != NULL ? state_text : _T("W")); if (state_brush != NULL) { /* colored background */ PixelRect rc; rc.left = paint_rc.left + Col2LeftScreenCoords; rc.top = paint_rc.top + Layout::FastScale(paint_rc_margin); rc.right = paint_rc.right - Layout::FastScale(paint_rc_margin); rc.bottom = paint_rc.bottom - Layout::FastScale(paint_rc_margin); canvas.fill_rectangle(rc, *state_brush); } if (state_text != NULL) { // -- status text will be centered inside its table cell: canvas.text(paint_rc.left + Col2LeftScreenCoords + Layout::FastScale(paint_rc_margin) + (statusColWidth / 2) - (canvas.text_width(state_text) / 2), (paint_rc.bottom + paint_rc.top - state_text_size.cy) / 2, state_text); } if (!warning.get_ack_expired()) canvas.set_text_color(old_text_color); if (CursorAirspace == &as) { update_vis = true; if (!warning.get_ack_expired()) { ack1_vis = false; ack_vis = false; } else { if (warning.get_warning_state() == AirspaceWarning::WARNING_INSIDE) { ack_vis = true; ack1_vis = false; } else { ack_vis = false; ack1_vis = true; } } ack2_vis = !warning.get_ack_day(); enable_vis = !warning.get_ack_expired(); } } // close scope if (update_vis) { wbAck1->set_visible(ack1_vis); wbAck2->set_visible(ack2_vis); wbAck->set_visible(ack_vis); wbEnable->set_visible(enable_vis); } }
WarningItem(const AirspaceWarning &warning) :airspace(&warning.GetAirspace()), state(warning.GetWarningState()), solution(warning.GetSolution()), ack_expired(warning.IsAckExpired()), ack_day(warning.GetAckDay()) {}
void Add(const AirspaceWarning& as) { if (as.GetWarningState() == AirspaceWarning::WARNING_INSIDE) ids_inside.checked_append(&as.GetAirspace()); else if (as.GetWarningState() > AirspaceWarning::WARNING_CLEAR) ids_warning.checked_append(&as.GetAirspace()); }
static void OnAirspaceListItemPaint(Canvas &canvas, const RECT paint_rc, unsigned i) { TCHAR sTmp[128]; ProtectedAirspaceWarningManager::Lease lease(airspace_warnings); if (lease->empty()) { assert(i == 0); canvas.text(paint_rc.left + IBLSCALE(2), paint_rc.top + IBLSCALE(2), _("No Warnings")); return; } assert(i < lease->size()); const AirspaceWarning* _warning = lease->get_warning(i); const AirspaceWarning warning = *_warning; const AbstractAirspace& as = warning.get_airspace(); const AirspaceInterceptSolution& solution = warning.get_solution(); tstring sName = as.get_name_text(false); tstring sTop = as.get_top_text(true); tstring sBase = as.get_base_text(true); tstring sType = as.get_type_text(true); const int TextHeight = 12, TextTop = 1; const int Col0Left = 3, Col1Left = 120, Col2Left = 200; RECT rcTextClip; rcTextClip = paint_rc; rcTextClip.right = IBLSCALE(Col1Left - 2); Color old_text_color = canvas.get_text_color(); if (!warning.get_ack_expired()) canvas.set_text_color(Color::GRAY); { // name, altitude info _stprintf(sTmp, _T("%-20s"), sName.c_str()); canvas.text_clipped(paint_rc.left + IBLSCALE(Col0Left), paint_rc.top + IBLSCALE(TextTop), rcTextClip, sTmp); _stprintf(sTmp, _T("%-20s"), sTop.c_str()); canvas.text(paint_rc.left + IBLSCALE(Col1Left), paint_rc.top + IBLSCALE(TextTop), sTmp); _stprintf(sTmp, _T("%-20s"), sBase.c_str()); canvas.text(paint_rc.left + IBLSCALE(Col1Left), paint_rc.top + IBLSCALE(TextTop + TextHeight), sTmp); } if (warning.get_warning_state() != AirspaceWarning::WARNING_INSIDE && warning.get_warning_state() > AirspaceWarning::WARNING_CLEAR) { _stprintf(sTmp, _T("%d secs dist %d m"), (int)solution.elapsed_time, (int)solution.distance); canvas.text_clipped(paint_rc.left + IBLSCALE(Col0Left), paint_rc.top + IBLSCALE(TextTop + TextHeight), rcTextClip, sTmp); } /* draw the warning state indicator */ Brush *state_brush; const TCHAR *state_text; if (warning.get_warning_state() == AirspaceWarning::WARNING_INSIDE) { if (warning.get_ack_expired()) state_brush = &hBrushInsideBk; else state_brush = &hBrushInsideAckBk; state_text = _T("inside"); } else if (warning.get_warning_state() > AirspaceWarning::WARNING_CLEAR) { if (warning.get_ack_expired()) state_brush = &hBrushNearBk; else state_brush = &hBrushNearAckBk; state_text = _T("near"); } else { state_brush = NULL; state_text = NULL; } const SIZE state_text_size = canvas.text_size(state_text != NULL ? state_text : _T("W")); if (state_brush != NULL) { /* colored background */ RECT rc; rc.left = paint_rc.left + Layout::FastScale(Col2Left); rc.top = paint_rc.top + Layout::FastScale(2); rc.right = rc.left + state_text_size.cx + Layout::FastScale(4); rc.bottom = paint_rc.bottom - Layout::FastScale(2); canvas.fill_rectangle(rc, *state_brush); } if (state_text != NULL) canvas.text(paint_rc.left + Layout::FastScale(Col2Left + 2), (paint_rc.bottom + paint_rc.top - state_text_size.cy) / 2, state_text); /* TCHAR sAckIndicator[6] = _T(" -++*"); if (pAS.Inside){ _stprintf(sTmp, _T("> %c %s"), sAckIndicator[pAS.Acknowledge], sType); } else { TCHAR DistanceText[MAX_PATH]; if (pAS.hDistance == 0) { // Directly above or below airspace Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7); if (pAS.vDistance > 0) { _stprintf(sTmp, _T("< %c %s ab %s"), sAckIndicator[pAS.Acknowledge], sType, DistanceText); } if (pAS.vDistance < 0) { Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7); _stprintf(sTmp, _T("< %c %s bl %s"), sAckIndicator[pAS.Acknowledge], sType, DistanceText); } } else { if ((pAS.vDistance == 0) || (pAS.hDistance < abs(pAS.vDistance)*30 )) { // Close to airspace altitude, horizontally separated Units::FormatUserDistance(fabs((double)pAS.hDistance),DistanceText, 7); _stprintf(sTmp, _T("< %c %s H %s"), sAckIndicator[pAS.Acknowledge], sType, DistanceText); } else { // Effectively above or below airspace, steep climb or descent // necessary to enter Units::FormatUserAltitude(fabs((double)pAS.vDistance),DistanceText, 7); if (pAS.vDistance > 0) { _stprintf(sTmp, _T("< %c %s ab %s"), sAckIndicator[pAS.Acknowledge], sType, DistanceText); } else { _stprintf(sTmp, _T("< %c %s bl %s"), sAckIndicator[pAS.Acknowledge], sType, DistanceText); } } } } canvas.text_clipped(paint_rc.left + IBLSCALE(Col0Left), paint_rc.top + IBLSCALE(TextTop + TextHeight), rcTextClip, sTmp); */ if (!warning.get_ack_expired()) canvas.set_text_color(old_text_color); }