Example #1
0
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;
}
Example #2
0
bool
AbstractAirspace::Intercept(const AircraftState &state,
                            const AirspaceAircraftPerformance &perf,
                            AirspaceInterceptSolution &solution,
                            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
    ? fixed(0)
    : state.location.Distance(loc_start);

  const auto distance_end = loc_start == loc_end
    ? distance_start
    : (only_vertical ? fixed(0) : state.location.Distance(loc_end));

  AirspaceInterceptSolution solution_this =
    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.IsValid() &&
        ((solution_candidate.elapsed_time < solution_this.elapsed_time) ||
         negative(solution_this.elapsed_time)))
      solution_this = solution_candidate;


    if (distance_end != distance_start) {
      // need to search far wall also
      solution_candidate = InterceptVertical(state, perf, distance_end);
      if (solution_candidate.IsValid() &&
          ((solution_candidate.elapsed_time < solution_this.elapsed_time) ||
           negative(solution_this.elapsed_time)))
        solution_this = solution_candidate;
    }
  }

  solution_candidate = InterceptHorizontal(state, perf, distance_start,
                                           distance_end, false);
  // search top wall
  if (solution_candidate.IsValid() &&
      ((solution_candidate.elapsed_time < solution_this.elapsed_time) ||
       negative(solution_this.elapsed_time)))
    solution_this = solution_candidate;

  // search bottom wall
  if (!altitude_base.IsTerrain()) {
    solution_candidate = InterceptHorizontal(state, perf, distance_start,
                                             distance_end, true);
    if (solution_candidate.IsValid() &&
        ((solution_candidate.elapsed_time < solution_this.elapsed_time) ||
         negative(solution_this.elapsed_time)))
      solution_this = solution_candidate;
  }

  if (solution_this.IsValid()) {
    solution = solution_this;
    if (solution.distance == distance_start)
      solution.location = loc_start;
    else if (solution.distance == distance_end)
      solution.location = loc_end;
    else if (positive(distance_end))
      solution.location =
        state.location.Interpolate(loc_end, solution.distance / distance_end);
    else
      solution.location = loc_start;

    assert(!negative(solution.distance));
    return true;
  }
  else
    solution = AirspaceInterceptSolution::Invalid();

  return false;
}