inline void RouteComputer::TerrainWarning(const MoreData &basic, DerivedInfo &calculated, const RoutePlannerConfig &config) { const AircraftState as = ToAircraftState(basic, calculated); const GlideResult& sol = calculated.task_stats.current_leg.solution_remaining; if (!sol.IsDefined()) { calculated.terrain_warning = false; return; } const AGeoPoint start (as.location, as.altitude); const RoughAltitude h_ceiling(std::max((int)basic.nav_altitude+500, (int)calculated.thermal_band.working_band_ceiling)); // allow at least 500m of climb above current altitude as ceiling, in case // there are no actual working band stats. GeoVector v = sol.vector; if (v.distance > fixed(200000)) /* limit to reasonable distances (200km max.) to avoid overflow in GeoVector::EndPoint() */ v.distance = fixed(200000); if (terrain) { if (sol.IsDefined()) { const AGeoPoint dest(v.EndPoint(start), sol.min_arrival_altitude); bool dirty = route_clock.CheckAdvance(basic.time); if (!dirty) { dirty = calculated.common_stats.active_taskpoint_index != last_active_tp || calculated.common_stats.task_type != last_task_type; if (dirty) { // restart clock route_clock.CheckAdvance(basic.time); route_clock.Reset(); } } last_task_type = calculated.common_stats.task_type; last_active_tp = calculated.common_stats.active_taskpoint_index; if (dirty) { protected_route_planner.SolveRoute(dest, start, config, h_ceiling); calculated.planned_route = route_planner.GetSolution(); calculated.terrain_warning = route_planner.Intersection(start, dest, calculated.terrain_warning_location); } return; } else { protected_route_planner.SolveRoute(start, start, config, h_ceiling); calculated.planned_route = route_planner.GetSolution(); } } calculated.terrain_warning = false; }
void AirspaceXSRenderer::Draw(Canvas &canvas, const ChartRenderer &chart, const Airspaces &database, const GeoPoint &start, const GeoVector &vec, const AircraftState &state) const { canvas.Select(*look.name_font); // Create IntersectionVisitor to render to the canvas AirspaceIntersectionVisitorSlice ivisitor( canvas, chart, settings, look, start, state); // Call visitor with intersecting airspaces database.VisitIntersecting(start, vec.EndPoint(start), ivisitor); }
static void AddSpiralWaypoints(Waypoints &waypoints, const GeoPoint ¢er = GeoPoint(Angle::Degrees(51.4), Angle::Degrees(7.85)), Angle angle_start = Angle::Degrees(0), Angle angle_step = Angle::Degrees(15), fixed distance_start = fixed(0), fixed distance_step = fixed(1000), fixed distance_max = fixed(150000)) { assert(positive(distance_step)); for (unsigned i = 0;; ++i) { GeoVector vector; vector.distance = distance_start + distance_step * i; if (vector.distance > distance_max) break; vector.bearing = angle_start + angle_step * i; Waypoint waypoint; waypoint.location = vector.EndPoint(center); waypoint.original_id = i; waypoint.elevation = fixed(i * 10 - 500); StaticString<256> buffer; if (i % 7 == 0) { buffer = _T("Airfield"); waypoint.type = Waypoint::Type::AIRFIELD; } else if (i % 3 == 0) { buffer = _T("Field"); waypoint.type = Waypoint::Type::OUTLANDING; } else buffer = _T("Waypoint"); buffer.AppendFormat(_T(" #%d"), i + 1); waypoint.name = buffer; waypoints.Append(std::move(waypoint)); } waypoints.Optimise(); }