gcc_pure NearestAirspace NearestAirspace::FindVertical(const MoreData &basic, const DerivedInfo &calculated, const ProtectedAirspaceWarningManager &airspace_warnings, const Airspaces &airspace_database) { if (!basic.location_available || (!basic.baro_altitude_available && !basic.gps_altitude_available)) /* can't check for airspaces without a GPS fix and altitude value */ return NearestAirspace(); /* find the nearest airspace */ AltitudeState altitude; altitude.altitude = basic.nav_altitude; altitude.altitude_agl = calculated.altitude_agl; const AbstractAirspace *nearest = nullptr; double nearest_delta = 100000; const ActiveAirspacePredicate active_predicate(&airspace_warnings); for (const auto &i : airspace_database.QueryInside(basic.location)) { const AbstractAirspace &airspace = i.GetAirspace(); if (!active_predicate(airspace)) continue; /* check delta below */ auto base = airspace.GetBase().GetAltitude(altitude); auto base_delta = base - altitude.altitude; if (base_delta >= 0 && base_delta < fabs(nearest_delta)) { nearest = &airspace; nearest_delta = base_delta; } /* check delta above */ auto top = airspace.GetTop().GetAltitude(altitude); auto top_delta = altitude.altitude - top; if (top_delta >= 0 && top_delta < fabs(nearest_delta)) { nearest = &airspace; nearest_delta = -top_delta; } } if (nearest == nullptr) return NearestAirspace(); return NearestAirspace(*nearest, nearest_delta); }
gcc_pure NearestAirspace NearestAirspace::FindHorizontal(const MoreData &basic, const ProtectedAirspaceWarningManager &airspace_warnings, const Airspaces &airspace_database) { if (!basic.location_available) /* can't check for airspaces without a GPS fix */ return NearestAirspace(); /* find the nearest airspace */ //consider only active airspaces const auto outside_and_active = MakeAndPredicate(ActiveAirspacePredicate(&airspace_warnings), OutsideAirspacePredicate(AGeoPoint(basic.location, 0))); //if altitude is available, filter airspaces in same height as airplane if (basic.NavAltitudeAvailable()) { /* check altitude; hard-coded margin of 50m (for now) */ const auto outside_and_active_and_height = MakeAndPredicate(outside_and_active, AirspacePredicateHeightRange(basic.nav_altitude - 50, basic.nav_altitude + 50)); const auto predicate = WrapAirspacePredicate(outside_and_active_and_height); return ::FindHorizontal(basic.location, airspace_database, predicate); } else { /* only filter outside and active */ const auto predicate = WrapAirspacePredicate(outside_and_active); return ::FindHorizontal(basic.location, airspace_database, predicate); } }
static inline NearestAirspace CalculateNearestAirspaceHorizontal(const GeoPoint &location, const FlatProjection &projection, const AbstractAirspace &airspace) { const auto closest = airspace.ClosestPoint(location, projection); assert(closest.IsValid()); return NearestAirspace(airspace, closest.DistanceS(location)); }
gcc_pure static NearestAirspace FindNearestVerticalAirspace() { const MoreData &basic = CommonInterface::Basic(); if (!basic.location_available || (!basic.baro_altitude_available && !basic.gps_altitude_available)) /* can't check for airspaces without a GPS fix and altitude value */ return NearestAirspace(); /* find the nearest airspace */ VerticalAirspaceVisitor visitor(basic, CommonInterface::Calculated()); airspace_database.VisitInside(basic.location, visitor); if (visitor.GetNearest() == NULL) return NearestAirspace(); return NearestAirspace(*visitor.GetNearest(), visitor.GetNearestDelta()); }
gcc_pure NearestAirspace NearestAirspace::FindVertical(const MoreData &basic, const DerivedInfo &calculated, const ProtectedAirspaceWarningManager &airspace_warnings, const Airspaces &airspace_database) { if (!basic.location_available || (!basic.baro_altitude_available && !basic.gps_altitude_available)) /* can't check for airspaces without a GPS fix and altitude value */ return NearestAirspace(); /* find the nearest airspace */ VerticalAirspaceVisitor visitor(basic, calculated, airspace_warnings); airspace_database.VisitInside(basic.location, visitor); if (visitor.GetNearest() == nullptr) return NearestAirspace(); return NearestAirspace(*visitor.GetNearest(), visitor.GetNearestDelta()); }
gcc_pure static NearestAirspace FindNearestHorizontalAirspace() { const MoreData &basic = CommonInterface::Basic(); if (!basic.location_available) /* can't check for airspaces without a GPS fix */ return NearestAirspace(); /* find the nearest airspace */ HorizontalAirspaceCondition condition(basic, CommonInterface::Calculated()); const Airspace *airspace = airspace_database.FindNearest(basic.location, condition); if (airspace == NULL) return NearestAirspace(); const AbstractAirspace &as = *airspace->GetAirspace(); /* calculate distance to the nearest point */ const GeoPoint closest = as.ClosestPoint(basic.location, airspace_database.GetProjection()); return NearestAirspace(as, basic.location.Distance(closest)); }
gcc_pure NearestAirspace NearestAirspace::FindHorizontal(const MoreData &basic, const ProtectedAirspaceWarningManager &airspace_warnings, const Airspaces &airspace_database) { if (!basic.location_available) /* can't check for airspaces without a GPS fix */ return NearestAirspace(); /* find the nearest airspace */ //consider only active airspaces const WrapAirspacePredicate<ActiveAirspacePredicate> active_predicate(&airspace_warnings); const WrapAirspacePredicate<OutsideAirspacePredicate> outside_predicate(AGeoPoint(basic.location, RoughAltitude(0))); const AndAirspacePredicate outside_and_active_predicate(active_predicate, outside_predicate); const Airspace *airspace; //if altitude is available, filter airspaces in same height as airplane if (basic.NavAltitudeAvailable()) { /* check altitude; hard-coded margin of 50m (for now) */ WrapAirspacePredicate<AirspacePredicateHeightRange> height_range_predicate(RoughAltitude(basic.nav_altitude-fixed(50)), RoughAltitude(basic.nav_altitude+fixed(50))); AndAirspacePredicate and_predicate(outside_and_active_predicate, height_range_predicate); airspace = airspace_database.FindNearest(basic.location, and_predicate); } else //only filter outside and active airspace = airspace_database.FindNearest(basic.location, outside_and_active_predicate); if (airspace == nullptr) return NearestAirspace(); const AbstractAirspace &as = airspace->GetAirspace(); /* calculate distance to the nearest point */ const GeoPoint closest = as.ClosestPoint(basic.location, airspace_database.GetProjection()); return NearestAirspace(as, basic.location.Distance(closest)); }