/** * 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; } }
void intersection(const AbstractAirspace &as) { *fout << "# intersection point\n"; for (auto it = intersections.begin(); it != intersections.end(); ++it) { const GeoPoint start = (it->first); const GeoPoint end = (it->second); *fout << start.longitude << " " << start.latitude << " " << "\n"; *fout << end.longitude << " " << end.latitude << " " << "\n\n"; } AirspaceInterceptSolution solution = Intercept(as, m_state, m_perf); if (solution.IsValid()) { *iout << "# intercept " << solution.elapsed_time << " h " << solution.altitude << "\n"; *iout << solution.location.longitude << " " << solution.location.latitude << " " << "\n\n"; } }
void closest(const AbstractAirspace &as) { GeoPoint c = as.ClosestPoint(state.location, projection); if (fout) { *fout << "# closest point\n"; *fout << c.longitude << " " << c.latitude << " " << "\n"; *fout << state.location.longitude << " " << state.location.latitude << " " << "\n\n"; } GeoVector vec(state.location, c); vec.distance = fixed(20000); // set big distance (for testing) const AirspaceInterceptSolution solution = as.Intercept(state, vec.EndPoint(state.location), projection, m_perf); if (solution.IsValid()) { if (fout) { *fout << "# intercept in " << solution.elapsed_time << " h " << solution.altitude << "\n"; } } }
AirspaceInterceptSolution AbstractAirspace::Intercept(const AircraftState &state, const AirspaceAircraftPerformance &perf, const GeoPoint &loc_start, const GeoPoint &loc_end) const { const bool only_vertical = (loc_start == loc_end) && (loc_start == state.location); const auto distance_start = only_vertical ? double(0) : state.location.Distance(loc_start); const auto distance_end = loc_start == loc_end ? distance_start : (only_vertical ? double(0) : state.location.Distance(loc_end)); AirspaceInterceptSolution solution = AirspaceInterceptSolution::Invalid(); // need to scan at least three sides, top, far, bottom (if not terrain) AirspaceInterceptSolution solution_candidate = AirspaceInterceptSolution::Invalid(); if (!only_vertical) { solution_candidate = InterceptVertical(state, perf, distance_start); // search near wall if (solution_candidate.IsEarlierThan(solution)) solution = solution_candidate; if (distance_end != distance_start) { // need to search far wall also solution_candidate = InterceptVertical(state, perf, distance_end); if (solution_candidate.IsEarlierThan(solution)) solution = solution_candidate; } } solution_candidate = InterceptHorizontal(state, perf, distance_start, distance_end, false); // search top wall if (solution_candidate.IsEarlierThan(solution)) solution = solution_candidate; // search bottom wall if (!altitude_base.IsTerrain()) { solution_candidate = InterceptHorizontal(state, perf, distance_start, distance_end, true); if (solution_candidate.IsEarlierThan(solution)) solution = solution_candidate; } if (solution.IsValid()) { if (solution.distance == distance_start) solution.location = loc_start; else if (solution.distance == distance_end) solution.location = loc_end; else if (distance_end > 0) solution.location = state.location.Interpolate(loc_end, solution.distance / distance_end); else solution.location = loc_start; assert(solution.distance >= 0); } return solution; }
bool IsEarlierThan(const AirspaceInterceptSolution &other) const { return IsValid() && (!other.IsValid() || elapsed_time < other.elapsed_time); }