Esempio n. 1
0
fixed
DoubleDistance(const GeoPoint &loc1, const GeoPoint &loc2,
               const GeoPoint &loc3)
{
  assert(loc1.IsValid());
  assert(loc2.IsValid());
  assert(loc3.IsValid());

  const fixed cos_loc1_lat = loc1.latitude.cos();
  const fixed cos_loc2_lat = loc2.latitude.cos();
  const fixed cos_loc3_lat = loc3.latitude.cos();

  const fixed s21 = (loc2.latitude - loc1.latitude).accurate_half_sin();
  const fixed sl21 = (loc2.longitude - loc1.longitude).accurate_half_sin();
  const fixed s32 = (loc3.latitude - loc2.latitude).accurate_half_sin();
  const fixed sl32 = (loc3.longitude - loc2.longitude).accurate_half_sin();

  const fixed a12 = sqr(s21)
    + SmallMult(cos_loc1_lat, cos_loc2_lat) * sqr(sl21);
  const fixed a23 = sqr(s32)
    + SmallMult(cos_loc2_lat, cos_loc3_lat) * sqr(sl32);

#ifdef INSTRUMENT_TASK
  count_distbearing++;
#endif

  return (2 * REARTH) *
    (EarthDistance(a12) + EarthDistance(a23)).Radians();
}
Esempio n. 2
0
gcc_pure
static GeoPoint
IntermediatePoint(const GeoPoint &loc1, const GeoPoint &loc2,
                  Angle dthis, Angle dtotal)
{
  assert(loc1.IsValid());
  assert(loc2.IsValid());

  if (loc1.longitude == loc2.longitude &&
      loc1.latitude == loc2.latitude)
    return loc1;

  if (!positive(dtotal.Native()))
    return loc1;

  assert(dthis <= dtotal && !negative(dthis.Native()));

  const fixed A = (dtotal - dthis).sin();
  const fixed B = dthis.sin();

  const auto sc1 = loc1.latitude.SinCos();
  const fixed sin_loc1_lat = sc1.first, cos_loc1_lat = sc1.second;

  const auto sc2 = loc2.latitude.SinCos();
  const fixed sin_loc2_lat = sc2.first, cos_loc2_lat = sc2.second;

  const auto sc3 = loc1.longitude.SinCos();
  const fixed sin_loc1_lon = sc3.first, cos_loc1_lon = sc3.second;

  const auto sc4 = loc2.longitude.SinCos();
  const fixed sin_loc2_lon = sc4.first, cos_loc2_lon = sc4.second;

  const fixed a_cos_loc1_lat = SmallMult(A, cos_loc1_lat);
  const fixed b_cos_loc2_lat = SmallMult(B, cos_loc2_lat);

  const fixed x = SmallMult(a_cos_loc1_lat, cos_loc1_lon)
    + SmallMult(b_cos_loc2_lat, cos_loc2_lon);
  const fixed y = SmallMult(a_cos_loc1_lat, sin_loc1_lon)
    + SmallMult(b_cos_loc2_lat, sin_loc2_lon);
  const fixed z = SmallMult(A, sin_loc1_lat) + SmallMult(B, sin_loc2_lat);

  GeoPoint loc3;
  loc3.latitude = Angle::FromXY(TinyHypot(x, y), z);
  loc3.longitude = Angle::FromXY(x, y);
  loc3.Normalize(); // ensure longitude is within -180:180

#ifdef INSTRUMENT_TASK
  count_distbearing++;
#endif

  return loc3;
}
Esempio n. 3
0
GeoPoint
FindLatitudeLongitudeS(const GeoPoint &loc, const Angle bearing,
                       double distance)
{
  assert(loc.IsValid());
  assert(distance >= 0);

  if (distance <= 0)
    return loc;

  const Angle distance_angle = FAISphere::EarthDistanceToAngle(distance);

  const auto scd = distance_angle.SinCos();
  const auto sin_distance = scd.first, cos_distance = scd.second;

  const auto scb = bearing.SinCos();
  const auto sin_bearing = scb.first, cos_bearing = scb.second;

  const auto scl = loc.latitude.SinCos();
  const auto sin_latitude = scl.first, cos_latitude = scl.second;

  GeoPoint loc_out;
  loc_out.latitude = Angle::asin(sin_latitude * cos_distance
                                 + cos_latitude * sin_distance * cos_bearing);

  loc_out.longitude = loc.longitude +
    Angle::FromXY(cos_distance - sin_latitude * loc_out.latitude.sin(),
                  sin_bearing * sin_distance * cos_latitude);

  loc_out.Normalize(); // ensure longitude is within -180:180

  return loc_out;
}
Esempio n. 4
0
inline double
OrderedTask::ScanDistanceMin(const GeoPoint &location, bool full)
{
  if (!full && location.IsValid() && last_min_location.IsValid() &&
      DistanceIsSignificant(location, last_min_location)) {
    const TaskWaypoint *active = GetActiveTaskPoint();
    if (active != nullptr) {
      const GeoPoint &target = active->GetWaypoint().location;
      const unsigned last_distance =
        (unsigned)last_min_location.Distance(target);
      const unsigned cur_distance =
        (unsigned)location.Distance(target);

      /* do the full scan only if the distance to the active task
         point has changed by more than 5%, otherwise we don't expect
         any relevant changes */
      if (last_distance < 2000 || cur_distance < 2000 ||
          last_distance * 20 >= cur_distance * 21 ||
          cur_distance * 20 >= last_distance * 21)
        full = true;
    }
  }

  if (full) {
    RunDijsktraMin(location);
    last_min_location = location;
  }

  return task_points.front()->ScanDistanceMin();
}
Esempio n. 5
0
inline GeoVector
TaskLeg::GetRemainingVector(const GeoPoint &ref) const
{
  switch (destination.GetActiveState()) {
  case OrderedTaskPoint::AFTER_ACTIVE:
    // this leg totally included
    return GetPlannedVector();

  case OrderedTaskPoint::CURRENT_ACTIVE: {
    // this leg partially included

    if (!ref.IsValid())
      /* if we don't have a GPS fix yet, we fall back to the "planned"
         vector unless this task leg has already been achieved */
      return destination.HasEntered()
        ? GeoVector::Zero()
        : GetPlannedVector();

    return memo_remaining.calc(ref, destination.GetLocationRemaining());
  }

  case OrderedTaskPoint::BEFORE_ACTIVE:
    // this leg not included
    return GeoVector::Zero();
  }

  gcc_unreachable();
  assert(false);
  return GeoVector::Invalid();
}
Esempio n. 6
0
static void
WriteEvent(JSON::ObjectWriter &object, const char *name,
           const BrokenDateTime &time, const GeoPoint &location)
{
  if (time.IsPlausible() || location.IsValid())
    object.WriteElement(name, WriteEventAttributes, time, location);
}
Esempio n. 7
0
GlideResult
TaskSolution::GlideSolutionRemaining(const GeoPoint &location,
                                     const GeoPoint &target,
                                     const fixed target_elevation,
                                     const fixed altitude,
                                     const SpeedVector &wind,
                                     const GlideSettings &settings,
                                     const GlidePolar &polar)
{
  assert(location.IsValid());
  assert(target.IsValid());

  GlideState gs(location.DistanceBearing(target),
                target_elevation, altitude, wind);

  return MacCready::Solve(settings, polar, gs);
}
Esempio n. 8
0
inline GeoVector
TaskLeg::GetTravelledVector(const GeoPoint &ref) const
{
  switch (destination.GetActiveState()) {
  case OrderedTaskPoint::BEFORE_ACTIVE:
    if (!GetOrigin())
      return GeoVector::Zero();

    // this leg totally included
    return memo_travelled.calc(GetOrigin()->GetLocationTravelled(),
                               destination.GetLocationTravelled());

  case OrderedTaskPoint::CURRENT_ACTIVE:
    // this leg partially included
    if (!GetOrigin())
      return GeoVector(0,
                       ref.IsValid()
                       ? ref.Bearing(destination.GetLocationRemaining())
                       : Angle::Zero());

    if (destination.HasEntered())
      return memo_travelled.calc(GetOrigin()->GetLocationTravelled(),
                                 destination.GetLocationTravelled());
    else if (!ref.IsValid())
      return GeoVector::Zero();
    else
      return memo_travelled.calc(GetOrigin()->GetLocationTravelled(), ref);

  case OrderedTaskPoint::AFTER_ACTIVE:
    if (!GetOrigin())
      return GeoVector::Zero();

    // this leg may be partially included
    if (GetOrigin()->HasEntered())
      return memo_travelled.calc(GetOrigin()->GetLocationTravelled(),
                                 ref.IsValid()
                                 ? ref
                                 : destination.GetLocationTravelled());

    return GeoVector::Zero();
  }

  gcc_unreachable();
  assert(false);
  return GeoVector::Invalid();
}
Esempio n. 9
0
/*
$GPRMB,<1>,,,,<5>,,,,,<10>,<11>,,<13>*hh<CR><LF>

<1>  Position Valid (A = valid, V = invalid)
<5>  Destination waypoint identifier, three digits
     (leading zeros will be transmitted)
<10> Range from present position to distination waypoint, format XXXX.X,
     nautical miles (leading zeros will be transmitted)
<11> Bearing from present position to destination waypoint, format XXX.X,
     degrees true (leading zeros will be transmitted)
<13> Arrival flag <A = arrival, V = not arrival)
*/
static bool
FormatGPRMB(char *buffer, size_t buffer_size, const GeoPoint& here,
            const AGeoPoint &destination)
{
  if (!here.IsValid() || !destination.IsValid())
    return false;

  const GeoVector vector(here, destination);
  const bool has_arrived = vector.distance < 1000; // < 1km ?

  snprintf(buffer, buffer_size, "GPRMB,%c,,,,,,,,,%06.1f,%04.1f,%c",
           here.IsValid() ? 'A' : 'V',
           (double)Units::ToUserUnit(vector.distance, Unit::NAUTICAL_MILES),
           (double)vector.bearing.Degrees(),
           has_arrived ? 'A' : 'V');

  return true;
}
Esempio n. 10
0
fixed
UnorderedTask::ScanDistanceRemaining(const GeoPoint &location)
{
  TaskPoint *tp = GetActiveTaskPoint();
  if (tp == nullptr || !location.IsValid())
    return fixed(0);

  return tp->Distance(location);
}
Esempio n. 11
0
inline fixed
TaskLeg::GetScoredDistance(const GeoPoint &ref) const
{
  if (!GetOrigin())
    return fixed(0);

  switch (destination.GetActiveState()) {
  case OrderedTaskPoint::BEFORE_ACTIVE:
    // this leg totally included
    return std::max(fixed(0),
                    GetOrigin()->GetLocationScored().Distance(destination.GetLocationScored())
                    - GetOrigin()->ScoreAdjustment()-destination.ScoreAdjustment());

  case OrderedTaskPoint::CURRENT_ACTIVE:
    // this leg partially included
    if (destination.HasEntered()) {
      return std::max(fixed(0),
                      GetOrigin()->GetLocationScored().Distance(destination.GetLocationScored())
                      - GetOrigin()->ScoreAdjustment()-destination.ScoreAdjustment());
    } else if (ref.IsValid())
      return std::max(fixed(0),
                      ref.ProjectedDistance(GetOrigin()->GetLocationScored(),
                                            destination.GetLocationScored())
                      -GetOrigin()->ScoreAdjustment());
    else
      return fixed(0);

  case OrderedTaskPoint::AFTER_ACTIVE:
    // this leg may be partially included
    if (GetOrigin()->HasEntered() && ref.IsValid()) {
      return std::max(fixed(0),
                      memo_travelled.calc(GetOrigin()->GetLocationScored(),
                                          ref).distance
                      -GetOrigin()->ScoreAdjustment());
    }

    return fixed(0);
  }

  gcc_unreachable();
  assert(false);
  return fixed(0);
}
Esempio n. 12
0
/**
 * Calculates the distance and bearing of two locations
 * @param loc1 Location 1
 * @param loc2 Location 2
 * @param Distance Pointer to the distance variable
 * @param Bearing Pointer to the bearing variable
 */
static void
DistanceBearingS(const GeoPoint &loc1, const GeoPoint &loc2,
                 Angle *distance, Angle *bearing)
{
  assert(loc1.IsValid());
  assert(loc2.IsValid());

  const auto sc1 = loc1.latitude.SinCos();
  fixed sin_lat1 = sc1.first, cos_lat1 = sc1.second;
  const auto sc2 = loc2.latitude.SinCos();
  fixed sin_lat2 = sc2.first, cos_lat2 = sc2.second;

  const Angle dlon = loc2.longitude - loc1.longitude;

  if (distance) {
    const fixed s1 = (loc2.latitude - loc1.latitude).accurate_half_sin();
    const fixed s2 = dlon.accurate_half_sin();
    const fixed a = sqr(s1) + SmallMult(cos_lat1, cos_lat2) * sqr(s2);

    Angle distance2 = EarthDistance(a);
    assert(!negative(distance2.Native()));
    *distance = distance2;
  }

  if (bearing) {
    // speedup for fixed since this is one call
    const auto sc = dlon.SinCos();
    const fixed sin_dlon = sc.first, cos_dlon = sc.second;

    const fixed y = SmallMult(sin_dlon, cos_lat2);
    const fixed x = SmallMult(cos_lat1, sin_lat2)
      - SmallMult(sin_lat1, cos_lat2, cos_dlon);

    *bearing = (x == fixed(0) && y == fixed(0))
      ? Angle::Zero()
      : Angle::FromXY(x, y).AsBearing();
  }

#ifdef INSTRUMENT_TASK
  count_distbearing++;
#endif
}
Esempio n. 13
0
void
ChartProjection::Set(const PixelRect &rc, const OrderedTask &task,
                     const GeoPoint &fallback_loc)
{
  GeoPoint center = task.GetTaskCenter();
  if (!center.IsValid())
    center = fallback_loc;

  const fixed radius = std::max(fixed(10000), task.GetTaskRadius());
  Set(rc, center, radius);
}
Esempio n. 14
0
void
FlatProjection::SetCenter(const GeoPoint &_center)
{
    assert(_center.IsValid());

    center = _center;

    cos = center.latitude.fastcosine() * fixed_scale;
    r_cos = 1. / cos;
    approx_scale = Unproject(FlatGeoPoint(0,-1)).DistanceS(Unproject(FlatGeoPoint(0,1))) / 2;
}
Esempio n. 15
0
void
DistanceBearingS(const GeoPoint &loc1, const GeoPoint &loc2,
                 Angle *distance, Angle *bearing)
{
  assert(loc1.IsValid());
  assert(loc2.IsValid());

  const auto sc1 = loc1.latitude.SinCos();
  auto sin_lat1 = sc1.first, cos_lat1 = sc1.second;
  const auto sc2 = loc2.latitude.SinCos();
  auto sin_lat2 = sc2.first, cos_lat2 = sc2.second;

  const Angle dlon = loc2.longitude - loc1.longitude;

  if (distance) {
    const auto s1 = (loc2.latitude - loc1.latitude).accurate_half_sin();
    const auto s2 = dlon.accurate_half_sin();
    const auto a = Square(s1) + cos_lat1 * cos_lat2 * Square(s2);

    Angle distance2 = EarthDistance(a);
    assert(!distance2.IsNegative());
    *distance = distance2;
  }

  if (bearing) {
    // speedup for fixed since this is one call
    const auto sc = dlon.SinCos();
    const auto sin_dlon = sc.first, cos_dlon = sc.second;

    const auto y = sin_dlon * cos_lat2;
    const auto x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon;

    *bearing = (x == fixed(0) && y == fixed(0))
      ? Angle::Zero()
      : Angle::FromXY(x, y).AsBearing();
  }

#ifdef INSTRUMENT_TASK
  count_distbearing++;
#endif
}
Esempio n. 16
0
  void Push(lua_State *L, GeoPoint value) {
    if (value.IsValid()) {
      lua_newtable(L);

      lua_newtable(L);
      SetField(L, -2, "__tostring", l_GeoPoint_tostring);
      lua_setmetatable(L, -2);

      SetField(L, -2, "longitude", value.longitude);
      SetField(L, -2, "latitude", value.latitude);
    } else
      lua_pushnil(L);
  }
Esempio n. 17
0
void
GeoBounds::Extend(const GeoPoint pt)
{
    if (!pt.IsValid())
        return;

    if (IsValid()) {
        longitude.Extend(pt.longitude);
        latitude.Extend(pt.latitude);
    } else {
        *this = GeoBounds(pt);
    }
}
Esempio n. 18
0
void
DistanceBearingS(const GeoPoint &loc1, const GeoPoint &loc2,
                 Angle *distance, Angle *bearing)
{
  assert(loc1.IsValid());
  assert(loc2.IsValid());

  const auto sc1 = loc1.latitude.SinCos();
  auto sin_lat1 = sc1.first, cos_lat1 = sc1.second;
  const auto sc2 = loc2.latitude.SinCos();
  auto sin_lat2 = sc2.first, cos_lat2 = sc2.second;

  const Angle dlon = loc2.longitude - loc1.longitude;

  if (distance) {
    const auto s1 = (loc2.latitude - loc1.latitude).accurate_half_sin();
    const auto s2 = dlon.accurate_half_sin();
    const auto a = Square(s1) + cos_lat1 * cos_lat2 * Square(s2);

    Angle distance2 = EarthDistance(a);
    assert(!distance2.IsNegative());
    *distance = distance2;
  }

  if (bearing) {
    const auto sc = dlon.SinCos();
    const auto sin_dlon = sc.first, cos_dlon = sc.second;

    const auto y = sin_dlon * cos_lat2;
    const auto x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon;

    *bearing = (x == 0 && y == 0)
      ? Angle::Zero()
      : Angle::FromXY(x, y).AsBearing();
  }
}
Esempio n. 19
0
static void
WriteEventAttributes(TextWriter &writer,
                     const BrokenDateTime &time, const GeoPoint &location)
{
  JSON::ObjectWriter object(writer);

  if (time.IsPlausible()) {
    NarrowString<64> buffer;
    FormatISO8601(buffer.buffer(), time);
    object.WriteElement("time", JSON::WriteString, buffer);
  }

  if (location.IsValid())
    JSON::WriteGeoPointAttributes(object, location);
}
Esempio n. 20
0
static void
Main()
{
  GeoPoint value = GeoPoint(Angle::Degrees(7.7061111111111114),
                            Angle::Degrees(51.051944444444445));

  if (!GeoPointEntryDialog(_T("The caption"), value, format, true))
    return;

  if (value.IsValid())
    _tprintf(_T("%s\n"),
             FormatGeoPoint(value, CoordinateFormat::DDMMSS).c_str());
  else
    printf("invalid\n");
}
Esempio n. 21
0
static void
Main()
{
  GeoPoint value = GeoPoint(Angle::Degrees(7.7061111111111114),
                            Angle::Degrees(51.051944444444445));

  if (!GeoPointEntryDialog(_T("The caption"), value, true))
    return;

  if (value.IsValid()) {
    TCHAR buffer[64];
    _tprintf(_T("%s\n"), FormatGeoPoint(value, buffer, ARRAY_SIZE(buffer),
                                        CoordinateFormat::DDMMSS));
  } else
    printf("invalid\n");
}
Esempio n. 22
0
bool
TargetMapWindow::isClickOnTarget(const PixelPoint pc) const
{
  if (task == nullptr)
    return false;

  ProtectedTaskManager::Lease task_manager(*task);
  const GeoPoint t = task_manager->GetLocationTarget(target_index);
  if (!t.IsValid())
    return false;

  const GeoPoint gp = projection.ScreenToGeo(pc.x, pc.y);
  if (projection.GeoToScreenDistance(gp.DistanceS(t)) < Layout::GetHitRadius())
    return true;

  return false;
}
Esempio n. 23
0
FlatGeoPoint
RoutePolars::ReachIntercept(const int index, const AFlatGeoPoint &flat_origin,
                            const GeoPoint &origin,
                            const RasterMap* map,
                            const FlatProjection &proj) const
{
  const bool valid = map && map->IsDefined();
  const int altitude = flat_origin.altitude - GetSafetyHeight();
  const FlatGeoPoint flat_dest = MSLIntercept(index, flat_origin,
                                              altitude, proj);

  if (!valid)
    return flat_dest;

  const GeoPoint dest = proj.Unproject(flat_dest);
  const GeoPoint p = map->Intersection(origin, altitude,
                                       altitude, dest, height_min_working);

  if (!p.IsValid())
    return flat_dest;

  FlatGeoPoint fp = proj.ProjectInteger(p);

  /* when there's an obstacle very nearby and our intersection is
     right next to our origin, the intersection may be deformed due to
     terrain raster rounding errors; the following code applies
     clipping to avoid degenerate polygons */
  FlatGeoPoint delta1 = flat_dest - (FlatGeoPoint)flat_origin;
  FlatGeoPoint delta2 = fp - (FlatGeoPoint)flat_origin;

  if (delta1.x * delta2.x < 0)
    /* intersection is on the wrong horizontal side */
    fp.x = flat_origin.x;

  if (delta1.y * delta2.y < 0)
    /* intersection is on the wrong vertical side */
    fp.x = flat_origin.y;

  return fp;
}
Esempio n. 24
0
GeoPoint
FindLatitudeLongitude(const GeoPoint &loc, const Angle bearing,
                      fixed distance)
{
  assert(loc.IsValid());

  assert(!negative(distance));
  if (!positive(distance))
    return loc;

  GeoPoint loc_out;

  const Angle distance_angle = EarthDistanceToAngle(distance);

  const auto scd = distance_angle.SinCos();
  const fixed sin_distance = scd.first, cos_distance = scd.second;

  const auto scb = bearing.SinCos();
  const fixed sin_bearing = scb.first, cos_bearing = scb.second;

  const auto scl = loc.latitude.SinCos();
  const fixed sin_latitude = scl.first, cos_latitude = scl.second;

  loc_out.latitude = EarthASin(SmallMult(sin_latitude, cos_distance)
                               + SmallMult(cos_latitude, sin_distance,
                                           cos_bearing));

  loc_out.longitude = loc.longitude +
    Angle::FromXY(cos_distance - SmallMult(sin_latitude,
                                           loc_out.latitude.sin()),
                  SmallMult(sin_bearing, sin_distance, cos_latitude));

  loc_out.Normalize(); // ensure longitude is within -180:180

#ifdef INSTRUMENT_TASK
  count_distbearing++;
#endif

  return loc_out;
}
Esempio n. 25
0
 bool IsValid() const {
   return center.IsValid();
 }
Esempio n. 26
0
 gcc_pure
 bool IsValid() const {
   return location.IsValid();
 }
Esempio n. 27
0
PyObject* xcsoar_Airspaces_addPolygon(Pyxcsoar_Airspaces *self, PyObject *args) {
  PyObject *py_points = nullptr,
           *py_name = nullptr,
           *py_as_class = nullptr,
           *py_base_ref = nullptr,
           *py_top_ref = nullptr;
  double base_alt, top_alt;

  if (!PyArg_ParseTuple(args, "OOOdOdO", &py_points, &py_name, &py_as_class,
                                         &base_alt, &py_base_ref,
                                         &top_alt, &py_top_ref)) {
    PyErr_SetString(PyExc_AttributeError, "Error reading attributes.");
    return nullptr;
  }

  /* Parse points */
  std::vector<GeoPoint> points;

  if (!PySequence_Check(py_points)) {
    PyErr_SetString(PyExc_ValueError, "First argument is no sequence");
    return nullptr;
  }

  Py_ssize_t num_items = PySequence_Fast_GET_SIZE(py_points);

  for (Py_ssize_t i = 0; i < num_items; ++i) {
    PyObject *py_location = PySequence_Fast_GET_ITEM(py_points, i);

    GeoPoint location = Python::ReadLonLat(py_location);

    if (!location.IsValid()) {
      if (PyErr_Occurred() == nullptr)
        PyErr_SetString(PyExc_RuntimeError, "Unknown error while parsing location");

      return nullptr;
    }

    points.push_back(location);
  }

  if (points.size() < 3) {
    PyErr_SetString(PyExc_ValueError, "Polygon has not enough points");
    return nullptr;
  }

  /* Parse airspace name */
  tstring name;

  if (!Python::PyStringToString(py_name, name)) {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace name.");
    return nullptr;
  }

  /* Parse airspace class */
  tstring as_class;
  AirspaceClass type = AirspaceClass::OTHER;

  if (!Python::PyStringToString(py_as_class, as_class)) {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace class.");
    return nullptr;
  }

  for (unsigned i = 0; i < ARRAY_SIZE(airspace_class_strings); i++) {
    if (as_class.compare(airspace_class_strings[i].string) == 0)
      type = airspace_class_strings[i].type;
  }

  /* Parse airspace base and top */
  tstring base_ref, top_ref;
  AirspaceAltitude base, top;

  if (!Python::PyStringToString(py_base_ref, base_ref)) {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace base reference.");
    return nullptr;
  }

  if (!Python::PyStringToString(py_top_ref, top_ref)) {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace top reference.");
    return nullptr;
  }

  if (base_ref.compare("MSL") == 0) {
    base.reference = AltitudeReference::MSL;
    base.altitude = base_alt;
  } else if (base_ref.compare("FL") == 0) {
    base.reference = AltitudeReference::STD;
    base.flight_level = base_alt;
  } else if (base_ref.compare("AGL") == 0) {
    base.reference = AltitudeReference::AGL;
    base.altitude_above_terrain = base_alt;
  } else {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace base.");
    return nullptr;
  }

  if (top_ref.compare("MSL") == 0) {
    top.reference = AltitudeReference::MSL;
    top.altitude = top_alt;
  } else if (top_ref.compare("FL") == 0) {
    top.reference = AltitudeReference::STD;
    top.flight_level = top_alt;
  } else if (top_ref.compare("AGL") == 0) {
    top.reference = AltitudeReference::AGL;
    top.altitude_above_terrain = top_alt;
  } else {
    PyErr_SetString(PyExc_ValueError, "Can't parse airspace top.");
    return nullptr;
  }

  /* Create airspace and save it into the database */
  AbstractAirspace *as = new AirspacePolygon(points);
  as->SetProperties(std::move(name), type, base, top);
  self->airspace_database->Add(as);

  Py_RETURN_NONE;
}
Esempio n. 28
0
 bool IsValid() const {
   return geo_location.IsValid();
 }