bool Airspaces::SynchroniseInRange(const Airspaces& master, const GeoPoint &location, const fixed range, const AirspacePredicate &condition) { bool changed = false; const AirspaceVector contents_master = master.ScanRange(location, range, condition); AirspaceVector contents_self; contents_self.reserve(std::max(airspace_tree.size(), contents_master.size())); task_projection = master.task_projection; // ensure these are up to date for (const auto &v : airspace_tree) contents_self.push_back(v); // find items to add for (const auto &v : contents_master) { const AbstractAirspace* other = v.GetAirspace(); bool found = false; for (auto s = contents_self.begin(); s != contents_self.end(); ++s) { const AbstractAirspace* self = s->GetAirspace(); if (self == other) { found = true; contents_self.erase(s); break; } } if (!found && other->IsActive()) { Add(v.GetAirspace()); changed = true; } } // anything left in the self list are items that were not in the query, // so delete them --- including the clearances! for (auto v = contents_self.begin(); v != contents_self.end();) { bool found = false; for (auto t = airspace_tree.begin(); t != airspace_tree.end(); ) { if (t->GetAirspace() == v->GetAirspace()) { AirspaceTree::const_iterator new_t = t; ++new_t; airspace_tree.erase_exact(*t); t = new_t; found = true; } else { ++t; } } assert(found); v->ClearClearance(); v = contents_self.erase(v); changed = true; } if (changed) Optimise(); return changed; }
const Airspaces::AirspaceVector Airspaces::FindInside(const AircraftState &state, const AirspacePredicate &condition) const { Airspace bb_target(state.location, task_projection); AirspaceVector vectors; airspace_tree.find_within_range(bb_target, 0, std::back_inserter(vectors)); #ifdef INSTRUMENT_TASK n_queries++; #endif for (auto v = vectors.begin(); v != vectors.end();) { #ifdef INSTRUMENT_TASK count_intersections++; #endif if (!condition(*v->GetAirspace()) || !(*v).IsInside(state)) vectors.erase(v); else ++v; } return vectors; }
void AirspaceWarningMonitor::Check() { const auto &calculated = CommonInterface::Calculated(); if (widget == nullptr && calculated.airspace_warnings.latest == last) return; /* there's a new airspace warning */ last = calculated.airspace_warnings.latest; auto *airspace_warnings = GetAirspaceWarnings(); if (airspace_warnings == nullptr) { HideWidget(); return; } if (!HasPointer()) { /* "classic" list-only view for devices without touch screen */ if (dlgAirspaceWarningVisible()) /* already visible */ return; // un-blank the display, play a sound ResetUserIdle(); PlayResource(_T("IDR_WAV_BEEPBWEEP")); // show airspace warnings dialog if (CommonInterface::GetUISettings().enable_airspace_warning_dialog) dlgAirspaceWarningsShowModal(*airspace_warnings, true); return; } const AbstractAirspace *airspace = nullptr; AirspaceWarning::State state; AirspaceInterceptSolution solution; { const ProtectedAirspaceWarningManager::Lease lease(*airspace_warnings); auto w = lease->begin(); if (w != lease->end() && w->IsAckExpired()) { airspace = &w->GetAirspace(); state = w->GetWarningState(); solution = w->GetSolution(); } } if (airspace == nullptr) { HideWidget(); return; } if (CommonInterface::GetUISettings().enable_airspace_warning_dialog) { /* show airspace warning */ if (widget != nullptr) { if (widget->Update(*airspace, state, solution)) return; HideWidget(); } widget = new AirspaceWarningWidget(*this, *airspace_warnings, *airspace, state, solution); PageActions::SetCustomBottom(widget); } // un-blank the display, play a sound ResetUserIdle(); PlayResource(_T("IDR_WAV_BEEPBWEEP")); }
static void TestOpenAir() { Airspaces airspaces; if (!ParseFile(Path(_T("test/data/airspace/openair.txt")), airspaces)) { skip(3, 0, "Failed to parse input file"); return; } const AirspaceClassTestCouple classes[] = { { _T("Class-R-Test"), RESTRICT }, { _T("Class-Q-Test"), DANGER }, { _T("Class-P-Test"), PROHIBITED }, { _T("Class-CTR-Test"), CTR }, { _T("Class-A-Test"), CLASSA }, { _T("Class-B-Test"), CLASSB }, { _T("Class-C-Test"), CLASSC }, { _T("Class-D-Test"), CLASSD }, { _T("Class-GP-Test"), NOGLIDER }, { _T("Class-W-Test"), WAVE }, { _T("Class-E-Test"), CLASSE }, { _T("Class-F-Test"), CLASSF }, { _T("Class-TMZ-Test"), TMZ }, { _T("Class-G-Test"), CLASSG }, { _T("Class-RMZ-Test"), RMZ }, }; ok1(airspaces.GetSize() == 24); const auto range = airspaces.QueryAll(); for (auto it = range.begin(); it != range.end(); ++it) { const AbstractAirspace &airspace = it->GetAirspace(); if (StringIsEqual(_T("Circle-Test"), airspace.GetName())) { if (!ok1(airspace.GetShape() == AbstractAirspace::Shape::CIRCLE)) continue; const AirspaceCircle &circle = (const AirspaceCircle &)airspace; ok1(equals(circle.GetRadius(), Units::ToSysUnit(5, Unit::NAUTICAL_MILES))); ok1(equals(circle.GetReferenceLocation(), Angle::Degrees(1.091667), Angle::Degrees(0.091667))); } else if (StringIsEqual(_T("Polygon-Test"), airspace.GetName())) { if (!ok1(airspace.GetShape() == AbstractAirspace::Shape::POLYGON)) continue; const AirspacePolygon &polygon = (const AirspacePolygon &)airspace; const SearchPointVector &points = polygon.GetPoints(); if (!ok1(points.size() == 5)) continue; ok1(equals(points[0].GetLocation(), Angle::DMS(1, 30, 30), Angle::DMS(1, 30, 30, true))); ok1(equals(points[1].GetLocation(), Angle::DMS(1, 30, 30), Angle::DMS(1, 30, 30))); ok1(equals(points[2].GetLocation(), Angle::DMS(1, 30, 30, true), Angle::DMS(1, 30, 30))); ok1(equals(points[3].GetLocation(), Angle::DMS(1, 30, 30, true), Angle::DMS(1, 30, 30, true))); ok1(equals(points[4].GetLocation(), Angle::DMS(1, 30, 30), Angle::DMS(1, 30, 30, true))); } else if (StringIsEqual(_T("Radio-Test"), airspace.GetName())) { ok1(StringIsEqual(_T("130.125 MHz"), airspace.GetRadioText().c_str())); } else if (StringIsEqual(_T("Height-Test-1"), airspace.GetName())) { ok1(airspace.GetBase().IsTerrain()); ok1(airspace.GetTop().reference == AltitudeReference::MSL); ok1(equals(airspace.GetTop().altitude, Units::ToSysUnit(2000, Unit::FEET))); } else if (StringIsEqual(_T("Height-Test-2"), airspace.GetName())) { ok1(airspace.GetBase().reference == AltitudeReference::MSL); ok1(equals(airspace.GetBase().altitude, 0)); ok1(airspace.GetTop().reference == AltitudeReference::STD); ok1(equals(airspace.GetTop().flight_level, 65)); } else if (StringIsEqual(_T("Height-Test-3"), airspace.GetName())) { ok1(airspace.GetBase().reference == AltitudeReference::AGL); ok1(equals(airspace.GetBase().altitude_above_terrain, Units::ToSysUnit(100, Unit::FEET))); ok1(airspace.GetTop().reference == AltitudeReference::MSL); ok1(airspace.GetTop().altitude > Units::ToSysUnit(30000, Unit::FEET)); } else if (StringIsEqual(_T("Height-Test-4"), airspace.GetName())) { ok1(airspace.GetBase().reference == AltitudeReference::MSL); ok1(equals(airspace.GetBase().altitude, 100)); ok1(airspace.GetTop().reference == AltitudeReference::MSL); ok1(airspace.GetTop().altitude > Units::ToSysUnit(30000, Unit::FEET)); } else if (StringIsEqual(_T("Height-Test-5"), airspace.GetName())) { ok1(airspace.GetBase().reference == AltitudeReference::AGL); ok1(equals(airspace.GetBase().altitude, 100)); ok1(airspace.GetTop().reference == AltitudeReference::MSL); ok1(equals(airspace.GetTop().altitude, 450)); } else if (StringIsEqual(_T("Height-Test-6"), airspace.GetName())) { ok1(airspace.GetBase().reference == AltitudeReference::AGL); ok1(equals(airspace.GetBase().altitude_above_terrain, Units::ToSysUnit(50, Unit::FEET))); ok1(airspace.GetTop().reference == AltitudeReference::STD); ok1(equals(airspace.GetTop().flight_level, 50)); } else { for (unsigned i = 0; i < ARRAY_SIZE(classes); ++i) { if (StringIsEqual(classes[i].name, airspace.GetName())) ok1(airspace.GetType() == classes[i].type); } } } }
static void TestTNP() { Airspaces airspaces; if (!ParseFile(_T("test/data/airspace/tnp.sua"), airspaces)) { skip(3, 0, "Failed to parse input file"); return; } const AirspaceClassTestCouple classes[] = { { _T("Class-R-Test"), RESTRICT }, { _T("Class-Q-Test"), DANGER }, { _T("Class-P-Test"), PROHIBITED }, { _T("Class-CTR-Test"), CTR }, { _T("Class-A-Test"), CLASSA }, { _T("Class-B-Test"), CLASSB }, { _T("Class-C-Test"), CLASSC }, { _T("Class-D-Test"), CLASSD }, { _T("Class-W-Test"), WAVE }, { _T("Class-E-Test"), CLASSE }, { _T("Class-F-Test"), CLASSF }, { _T("Class-TMZ-Test"), TMZ }, { _T("Class-G-Test"), CLASSG }, }; ok1(airspaces.size() == 22); for (auto it = airspaces.begin(); it != airspaces.end(); ++it) { const AbstractAirspace &airspace = *it->GetAirspace(); if (_tcscmp(_T("Circle-Test"), airspace.GetName()) == 0) { if (!ok1(airspace.GetShape() == AbstractAirspace::Shape::CIRCLE)) continue; const AirspaceCircle &circle = (const AirspaceCircle &)airspace; ok1(equals(circle.GetRadius(), Units::ToSysUnit(fixed(5), Unit::NAUTICAL_MILES))); ok1(equals(circle.GetCenter(), Angle::Degrees(fixed(1.091667)), Angle::Degrees(fixed(0.091667)))); } else if (_tcscmp(_T("Polygon-Test"), airspace.GetName()) == 0) { if (!ok1(airspace.GetShape() == AbstractAirspace::Shape::POLYGON)) continue; const AirspacePolygon &polygon = (const AirspacePolygon &)airspace; const SearchPointVector &points = polygon.GetPoints(); if (!ok1(points.size() == 5)) continue; ok1(equals(points[0].GetLocation(), Angle::DMS(fixed(1), fixed(30), fixed(30)), Angle::DMS(fixed(1), fixed(30), fixed(30)).Flipped())); ok1(equals(points[1].GetLocation(), Angle::DMS(fixed(1), fixed(30), fixed(30)), Angle::DMS(fixed(1), fixed(30), fixed(30)))); ok1(equals(points[2].GetLocation(), Angle::DMS(fixed(1), fixed(30), fixed(30)).Flipped(), Angle::DMS(fixed(1), fixed(30), fixed(30)))); ok1(equals(points[3].GetLocation(), Angle::DMS(fixed(1), fixed(30), fixed(30)).Flipped(), Angle::DMS(fixed(1), fixed(30), fixed(30)).Flipped())); ok1(equals(points[4].GetLocation(), Angle::DMS(fixed(1), fixed(30), fixed(30)), Angle::DMS(fixed(1), fixed(30), fixed(30)).Flipped())); } else if (_tcscmp(_T("Radio-Test"), airspace.GetName()) == 0) { ok1(_tcscmp(_T("130.125 MHz"), airspace.GetRadioText().c_str()) == 0); } else if (_tcscmp(_T("Height-Test-1"), airspace.GetName()) == 0) { ok1(airspace.GetBase().IsTerrain()); ok1(airspace.GetTop().type == AirspaceAltitude::Type::MSL); ok1(equals(airspace.GetTop().altitude, Units::ToSysUnit(fixed(2000), Unit::FEET))); } else if (_tcscmp(_T("Height-Test-2"), airspace.GetName()) == 0) { ok1(airspace.GetBase().type == AirspaceAltitude::Type::MSL); ok1(equals(airspace.GetBase().altitude, 0)); ok1(airspace.GetTop().type == AirspaceAltitude::Type::FL); ok1(equals(airspace.GetTop().flight_level, 65)); } else if (_tcscmp(_T("Height-Test-3"), airspace.GetName()) == 0) { ok1(airspace.GetBase().type == AirspaceAltitude::Type::AGL); ok1(equals(airspace.GetBase().altitude_above_terrain, Units::ToSysUnit(fixed(100), Unit::FEET))); ok1(airspace.GetTop().type == AirspaceAltitude::Type::MSL); ok1(airspace.GetTop().altitude > Units::ToSysUnit(fixed(30000), Unit::FEET)); } else if (_tcscmp(_T("Height-Test-4"), airspace.GetName()) == 0) { ok1(airspace.GetBase().type == AirspaceAltitude::Type::MSL); ok1(equals(airspace.GetBase().altitude, 100)); ok1(airspace.GetTop().type == AirspaceAltitude::Type::MSL); ok1(airspace.GetTop().altitude > Units::ToSysUnit(fixed(30000), Unit::FEET)); } else if (_tcscmp(_T("Height-Test-5"), airspace.GetName()) == 0) { ok1(airspace.GetBase().type == AirspaceAltitude::Type::AGL); ok1(equals(airspace.GetBase().altitude, 100)); ok1(airspace.GetTop().type == AirspaceAltitude::Type::MSL); ok1(equals(airspace.GetTop().altitude, 450)); } else if (_tcscmp(_T("Height-Test-6"), airspace.GetName()) == 0) { ok1(airspace.GetBase().type == AirspaceAltitude::Type::AGL); ok1(equals(airspace.GetBase().altitude_above_terrain, Units::ToSysUnit(fixed(50), Unit::FEET))); ok1(airspace.GetTop().type == AirspaceAltitude::Type::FL); ok1(equals(airspace.GetTop().flight_level, 50)); } else { for (unsigned i = 0; i < ARRAY_SIZE(classes); ++i) { if (_tcscmp(classes[i].name, airspace.GetName()) == 0) ok1(airspace.GetType() == classes[i].type); } } } }
/** * Equality operator, matches if contained airspace is the same */ bool operator==(Airspace const &a) const { return &GetAirspace() == &a.GetAirspace(); }
/** * Equality operator, matches if contained airspace is the same */ bool operator==(Airspace const& a) const { return (GetAirspace() == a.GetAirspace()); }