Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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"));
}
Пример #4
0
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);
      }
    }
  }
}
Пример #5
0
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);
      }
    }
  }
}
Пример #6
0
 /**
  * Equality operator, matches if contained airspace is the same
  */
 bool operator==(Airspace const &a) const {
   return &GetAirspace() == &a.GetAirspace();
 }
Пример #7
0
 /**
  * Equality operator, matches if contained airspace is the same
  */
 bool operator==(Airspace const& a) const {
   return (GetAirspace() == a.GetAirspace());
 }