Beispiel #1
0
bool
GlueMapWindow::ShowMapItems(const GeoPoint &location,
                            bool show_empty_message) const
{
  fixed range = visible_projection.DistancePixelsToMeters(Layout::GetHitRadius());

  MapItemList list;
  MapItemListBuilder builder(list, location, range);

  builder.AddLocation(Basic(), terrain);

  if (route_planner)
    builder.AddArrivalAltitudes(*route_planner, terrain,
                                GetComputerSettings().task.safety_height_arrival);

  if (Basic().location_available)
    builder.AddSelfIfNear(Basic().location, Calculated().heading);

  if (task)
    builder.AddTaskOZs(*task);

  const Airspaces *airspace_database = airspace_renderer.GetAirspaces();
  if (airspace_database)
    builder.AddVisibleAirspace(*airspace_database,
                               airspace_renderer.GetWarningManager(),
                               GetComputerSettings().airspace,
                               GetMapSettings().airspace, Basic(),
                               Calculated());

  if (marks && render_projection.GetMapScale() <= fixed_int_constant(30000))
    builder.AddMarkers(*marks);

  if (render_projection.GetMapScale() <= fixed_int_constant(4000))
    builder.AddThermals(Calculated().thermal_locator, Basic(), Calculated());

  if (waypoints)
    builder.AddWaypoints(*waypoints);

  if (Basic().flarm.available)
    builder.AddTraffic(Basic().flarm);

  // Sort the list of map items
  list.Sort();

  // Show the list dialog
  if (list.empty()) {
    if (show_empty_message)
      ShowMessageBox(_("There is nothing interesting near this location."),
                  _("Map elements at this location"), MB_OK | MB_ICONINFORMATION);

    return false;
  }

  ShowMapItemListDialog(UIGlobals::GetMainWindow(), list,
                        UIGlobals::GetDialogLook(), look, traffic_look,
                        final_glide_bar_renderer.GetLook(), GetMapSettings(),
                        glide_computer != NULL
                        ? &glide_computer->GetAirspaceWarnings() : NULL);
  return true;
}
void
GlueMapWindow::UpdateMapScale()
{
    /* not using MapWindowBlackboard here because these methods are
       called by the main thread */
    const DerivedInfo &calculated = CommonInterface::Calculated();
    const MapSettings &settings = CommonInterface::GetMapSettings();

    if (GetDisplayMode() == DM_CIRCLING && settings.circle_zoom_enabled)
        return;

    if (!IsNearSelf())
        return;

    fixed wpd = calculated.auto_zoom_distance;
    if (settings.auto_zoom_enabled && positive(wpd)) {
        // Calculate distance percentage between plane symbol and map edge
        // 50: centered  100: at edge of map
        int AutoZoomFactor = (GetDisplayMode() == DM_CIRCLING) ?
                             50 : 100 - settings.glider_screen_position;
        // Leave 5% of full distance for target display
        AutoZoomFactor -= 5;
        // Adjust to account for map scale units
        AutoZoomFactor *= 8;
        wpd = wpd / ((fixed) AutoZoomFactor / fixed_int_constant(100));
        // Clip map auto zoom range to reasonable values
        wpd = max(fixed_int_constant(525),
                  min(settings.max_auto_zoom_distance / fixed_int_constant(10), wpd));
        visible_projection.SetFreeMapScale(wpd);
    }
}
void
InputEvents::sub_SetZoom(fixed value)
{
  MapSettings &settings_map = CommonInterface::SetMapSettings();
  GlueMapWindow *map_window = CommonInterface::main_window.ActivateMap();
  if (map_window == NULL)
    return;

  DisplayMode displayMode = XCSoarInterface::main_window.GetDisplayMode();
  if (settings_map.auto_zoom_enabled &&
      !(displayMode == DisplayMode::CIRCLING && settings_map.circle_zoom_enabled) &&
      !CommonInterface::IsPanning()) {
    settings_map.auto_zoom_enabled = false;  // disable autozoom if user manually changes zoom
    Profile::Set(szProfileAutoZoom, false);
    Message::AddMessage(_("Auto. zoom off"));
  }

  fixed vmin = CommonInterface::GetComputerSettings().polar.glide_polar_task.GetVMin();
  fixed scale_2min_distance = vmin * fixed_int_constant(12);
  const fixed scale_500m = fixed_int_constant(50);
  const fixed scale_1600km = fixed_int_constant(1600*100);
  fixed minreasonable = (displayMode == DisplayMode::CIRCLING) ?
                        scale_500m : max(scale_500m, scale_2min_distance);

  value = max(minreasonable, min(scale_1600km, value));
  map_window->SetMapScale(value);
  map_window->QuickRedraw();
}
Beispiel #4
0
void
TrackLineRenderer::Draw(Canvas &canvas, const Angle screen_angle,
                        const Angle track_angle, const RasterPoint pos)
{
  const auto sc = (track_angle - screen_angle).SinCos();
  const fixed x = sc.first, y = sc.second;

  RasterPoint end;
  end.x = pos.x + iround(x * fixed_int_constant(400));
  end.y = pos.y - iround(y * fixed_int_constant(400));

  canvas.Select(look.track_line_pen);
  canvas.DrawLine(pos, end);
}
Beispiel #5
0
void
GlueMapWindow::UpdateMapScale()
{
  /* not using MapWindowBlackboard here because these methods are
     called by the main thread */
  const DerivedInfo &calculated = CommonInterface::Calculated();
  const MapSettings &settings = CommonInterface::GetMapSettings();

  if (InCirclingMode() && settings.circle_zoom_enabled)
    return;

  if (!IsNearSelf())
    return;

  fixed distance = calculated.auto_zoom_distance;
  if (settings.auto_zoom_enabled && positive(distance)) {
    // Calculate distance percentage between plane symbol and map edge
    // 50: centered  100: at edge of map
    int auto_zoom_factor = InCirclingMode() ?
                           50 : 100 - settings.glider_screen_position;
    // Leave 5% of full distance for target display
    auto_zoom_factor -= 5;
    // Adjust to account for map scale units
    auto_zoom_factor *= 8;

    distance /= fixed(auto_zoom_factor) / 100;

    // Clip map auto zoom range to reasonable values
    distance = max(fixed_int_constant(525),
                   min(settings.max_auto_zoom_distance / 10, distance));

    visible_projection.SetFreeMapScale(distance);
  }
}
Beispiel #6
0
bool 
OLCTriangle::path_closed() const
{

  // RESERVED FOR FUTURE USE: DO NOT DELETE

  // note this may fail if resolution of sampled trace is too low
  assert(n_points > 0);
  const ScanTaskPoint end(0, n_points-1);
  fixed d_min(-1);

  ScanTaskPoint start(0, 0);

  assert(first_tp < n_points);
  for (start.point_index = 0; start.point_index <= first_tp;
       ++start.point_index) {

    const fixed d_this =
      GetPointFast(start).get_location().distance(
        GetPointFast(end).get_location());

    if (!positive(d_min) || (d_this < d_min)) {
      d_min = d_this;
    } 
    if (d_this<= fixed_int_constant(1000)) {
      return true;
    }
  }

  return false;
}
Beispiel #7
0
bool
OLCTriangle::IsPathClosed() const
{

  // RESERVED FOR FUTURE USE: DO NOT DELETE

  // note this may fail if resolution of sampled trace is too low
  assert(n_points > 0);

  const GeoPoint end_location = GetPoint(n_points - 1).GetLocation();

  fixed d_min(-1);

  assert(first_tp < n_points);

  for (unsigned start_index = 0; start_index <= first_tp; ++start_index) {
    const fixed d_this =
      GetPoint(start_index).GetLocation().Distance(end_location);

    if (!positive(d_min) || d_this < d_min)
      d_min = d_this;

    if (d_this<= fixed_int_constant(1000))
      return true;
  }

  return false;
}
Beispiel #8
0
void
MapWindow::RenderMarks(Canvas &canvas)
{
  if (marks != NULL &&
      render_projection.GetMapScale() <= fixed_int_constant(30000))
    marks->Draw(canvas, render_projection);
}
void 
AircraftStateFilter::update(const AIRCRAFT_STATE& state)
{
  fixed dt = state.Time- m_state_last.Time;

  if (negative(dt)) {
    reset(state);
    return;
  }

  if (!positive(dt))
    return;

  GeoVector vec(m_state_last.Location, state.Location);

  const fixed MACH_1 = fixed_int_constant(343);
  if (vec.Distance / dt > MACH_1) {
    reset(state);
    return;
  }

  m_x+= vec.Bearing.sin()*vec.Distance;
  m_y+= vec.Bearing.cos()*vec.Distance;

  m_vx = m_lpf_x.update(m_df_x.update(m_x));
  m_vy = m_lpf_y.update(m_df_y.update(m_y));
  m_vz = m_lpf_alt.update(m_df_alt.update(state.NavAltitude));

  m_state_last = state;
}
Beispiel #10
0
fixed
GlideResult::DestinationAngleGround() const
{
  if (positive(vector.distance))
    return (altitude_difference + pure_glide_height) / vector.distance;

  return fixed_int_constant(1000);
}
Beispiel #11
0
fixed
GlideResult::GlideAngleGround() const
{
  if (positive(vector.distance))
    return pure_glide_height / vector.distance;

  return fixed_int_constant(1000);
}
Beispiel #12
0
void
TargetMapWindow::set(ContainerWindow &parent, int left, int top,
                     unsigned width, unsigned height, WindowStyle style)
{
  projection.SetFreeMapScale(fixed_int_constant(5000));

  BufferWindow::set(parent, left, top, width, height, style);
}
fixed
GlideResult::destination_angle_ground() const
{
  if (positive(Vector.Distance))
    return (AltitudeDifference+HeightGlide) / Vector.Distance;

  return fixed_int_constant(1000);
}
fixed
GlideResult::glide_angle_ground() const
{
  if (positive(Vector.Distance))
    return HeightGlide / Vector.Distance;

  return fixed_int_constant(1000);
}
Beispiel #15
0
void
TargetMapWindow::set(ContainerWindow &parent,
                     PixelScalar left, PixelScalar top,
                     UPixelScalar width, UPixelScalar height,
                     WindowStyle style)
{
  projection.SetFreeMapScale(fixed_int_constant(5000));

  BufferWindow::set(parent, left, top, width, height, style);
}
Beispiel #16
0
void
MapWindow::set(ContainerWindow &parent, const PixelRect &rc)
{
  WindowStyle style;
  style.enable_double_clicks();
  DoubleBufferWindow::set(parent, rc.left, rc.top,
                          rc.right - rc.left, rc.bottom - rc.top,
                          style);

  // initialize other systems
  visible_projection.SetMapScale(fixed_int_constant(5000));
  visible_projection.SetScreenOrigin((rc.left + rc.right) / 2,
                                     (rc.bottom + rc.top) / 2);
  visible_projection.UpdateScreenBounds();

#ifndef ENABLE_OPENGL
  buffer_projection = visible_projection;
#endif
}
Beispiel #17
0
/**
 * Draws the FLARM traffic icons onto the given canvas
 * @param canvas Canvas for drawing
 */
void
MapWindow::DrawFLARMTraffic(Canvas &canvas,
                            const RasterPoint aircraft_pos) const
{
  // Return if FLARM icons on moving map are disabled
  if (!GetMapSettings().show_flarm_on_map)
    return;

  // Return if FLARM data is not available
  const FlarmState &flarm = Basic().flarm;
  if (!flarm.available)
    return;

  const WindowProjection &projection = render_projection;

  // if zoomed in too far out, dont draw traffic since it will be too close to
  // the glider and so will be meaningless (serves only to clutter, cant help
  // the pilot)
  if (projection.GetMapScale() > fixed_int_constant(7300))
    return;

  // Circle through the FLARM targets
  for (auto it = flarm.traffic.begin(), end = flarm.traffic.end();
      it != end; ++it) {
    const FlarmTraffic &traffic = *it;

    if (!traffic.location_available)
      continue;

    // Save the location of the FLARM target
    GeoPoint target_loc = traffic.location;

    // Points for the screen coordinates for the icon, name and average climb
    RasterPoint sc, sc_name, sc_av;

    // If FLARM target not on the screen, move to the next one
    if (!projection.GeoToScreenIfVisible(target_loc, sc))
      continue;

    // Draw the name 16 points below the icon
    sc_name = sc;
    sc_name.y -= Layout::Scale(20);

    // Draw the average climb value above the icon
    sc_av = sc;
    sc_av.y += Layout::Scale(5);

    TextInBoxMode mode;
    mode.mode = RM_OUTLINED;

    // JMW TODO enhancement: decluttering of FLARM altitudes (sort by max lift)

    int dx = sc_av.x - aircraft_pos.x;
    int dy = sc_av.y - aircraft_pos.y;

    // only draw labels if not close to aircraft
    if (dx * dx + dy * dy > Layout::Scale(30 * 30)) {
      // If FLARM callsign/name available draw it to the canvas
      if (traffic.HasName() && !StringIsEmpty(traffic.name))
        TextInBox(canvas, traffic.name, sc_name.x, sc_name.y,
                  mode, get_client_rect());

      if (traffic.climb_rate_avg30s >= fixed(0.1)) {
        // If average climb data available draw it to the canvas
        TCHAR label_avg[100];
        Units::FormatUserVerticalSpeed(traffic.climb_rate_avg30s,
                                       label_avg, false);
        TextInBox(canvas, label_avg, sc_av.x, sc_av.y, mode, get_client_rect());
      }
    }

    TrafficRenderer::Draw(canvas, traffic_look, traffic,
                          traffic.track - projection.GetScreenAngle(), sc);
  }
}
Beispiel #18
0
bool
GlueMapWindow::ShowMapItems(const GeoPoint &location,
                            bool show_empty_message) const
{
  /* not using MapWindowBlackboard here because this method is called
     by the main thread */
  const ComputerSettings &computer_settings =
    CommonInterface::GetComputerSettings();
  const MapSettings &settings = CommonInterface::GetMapSettings();
  const MoreData &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();

  fixed range = visible_projection.DistancePixelsToMeters(Layout::GetHitRadius());

  MapItemList list;
  MapItemListBuilder builder(list, location, range);

  if (settings.item_list.add_location)
      builder.AddLocation(basic, terrain);

  if (settings.item_list.add_arrival_altitude && route_planner)
    builder.AddArrivalAltitudes(*route_planner, terrain,
                                computer_settings.task.safety_height_arrival);

  if (basic.location_available)
    builder.AddSelfIfNear(basic.location, basic.attitude.heading);

  if (task)
    builder.AddTaskOZs(*task);

  const Airspaces *airspace_database = airspace_renderer.GetAirspaces();
  if (airspace_database)
    builder.AddVisibleAirspace(*airspace_database,
                               airspace_renderer.GetWarningManager(),
                               computer_settings.airspace,
                               settings.airspace, basic,
                               calculated);

  if (marks && visible_projection.GetMapScale() <= fixed_int_constant(30000))
    builder.AddMarkers(*marks);

  if (visible_projection.GetMapScale() <= fixed_int_constant(4000))
    builder.AddThermals(calculated.thermal_locator, basic, calculated);

  if (waypoints)
    builder.AddWaypoints(*waypoints);

#ifdef HAVE_NOAA
  if (noaa_store)
    builder.AddWeatherStations(*noaa_store);
#endif

  builder.AddTraffic(basic.flarm.traffic, computer_settings.team_code);

  // Sort the list of map items
  list.Sort();

  // Show the list dialog
  if (list.empty()) {
    if (show_empty_message)
      ShowMessageBox(_("There is nothing interesting near this location."),
                  _("Map elements at this location"), MB_OK | MB_ICONINFORMATION);

    return false;
  }

  ShowMapItemListDialog(UIGlobals::GetMainWindow(), list,
                        UIGlobals::GetDialogLook(), look, traffic_look,
                        final_glide_bar_renderer.GetLook(), settings,
                        glide_computer != NULL
                        ? &glide_computer->GetAirspaceWarnings() : NULL);
  return true;
}
void
WaypointIconRenderer::DrawLandable(const Waypoint &waypoint,
                                   const RasterPoint &point,
                                   Reachability reachable)
{

  if (!settings.vector_landable_rendering) {
    const MaskedIcon *icon;

    if (reachable == ReachableTerrain)
      icon = waypoint.IsAirport()
        ? &look.airport_reachable_icon
        : &look.field_reachable_icon;
    else if (reachable == ReachableStraight)
      icon = waypoint.IsAirport()
        ? &look.airport_marginal_icon
        : &look.field_marginal_icon;
    else
      icon = waypoint.IsAirport()
        ? &look.airport_unreachable_icon
        : &look.field_unreachable_icon;

    icon->draw(canvas, point);
    return;
  }

  // SW rendering of landables
  fixed scale = fixed(Layout::SmallScale(settings.landable_rendering_scale)) /
                fixed_int_constant(150);
  fixed radius = fixed_int_constant(10) * scale;

  canvas.black_pen();
  if (settings.landable_style == wpLandableWinPilot) {
    // Render landable with reachable state
    if (reachable != Unreachable) {
      canvas.select(reachable == ReachableTerrain
                    ? look.reachable_brush
                    : look.terrain_unreachable_brush);
      DrawLandableBase(canvas, point, waypoint.IsAirport(),
                       radius + radius / fixed_two);
    }
    canvas.select(look.magenta_brush);
  } else if (settings.landable_style == wpLandableAltB) {
    if (reachable != Unreachable)
      canvas.select(reachable == ReachableTerrain
                    ? look.reachable_brush
                    : look.orange_brush);
    else
      canvas.select(look.unreachable_brush);
  } else {
    if (reachable != Unreachable)
      canvas.select(reachable == ReachableTerrain
                    ? look.reachable_brush
                    : look.terrain_unreachable_brush);
    else if (waypoint.IsAirport())
      canvas.select(look.white_brush);
    else
      canvas.select(look.light_gray_brush);
  }
  DrawLandableBase(canvas, point, waypoint.IsAirport(), radius);

  // Render runway indication
  const Runway &runway = waypoint.runway;
  if (runway.IsDirectionDefined()) {
    fixed len;
    if (settings.scale_runway_length && runway.IsLengthDefined())
      len = (radius / fixed_two) +
        (((int) runway.GetLength() - 500) / 500) * (radius / fixed_four);
    else
      len = radius;
    len += fixed_two * scale;
    Angle runwayDrawingAngle = runway.GetDirection() - screen_rotation;
    canvas.select(look.white_brush);
    DrawLandableRunway(canvas, point, runwayDrawingAngle, len,
                       fixed_int_constant(5) * scale);
  }
}
Beispiel #20
0
void
GlueMapWindow::UpdateProjection()
{
  const PixelRect rc = GetClientRect();

  /* not using MapWindowBlackboard here because these methods are
     called by the main thread */
  const NMEAInfo &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();
  const MapSettings &settings_map = CommonInterface::GetMapSettings();

  RasterPoint center;
  center.x = (rc.left + rc.right) / 2;
  center.y = (rc.top + rc.bottom) / 2;

  if (InCirclingMode() || !IsNearSelf())
    visible_projection.SetScreenOrigin(center.x, center.y);
  else if (settings_map.cruise_orientation == NORTHUP) {
    RasterPoint offset{0, 0};
    if (settings_map.glider_screen_position != 50 &&
        settings_map.map_shift_bias != MAP_SHIFT_BIAS_NONE) {
      fixed x = fixed_zero;
      fixed y = fixed_zero;
      if (settings_map.map_shift_bias == MAP_SHIFT_BIAS_TRACK) {
        if (basic.track_available &&
            basic.ground_speed_available &&
             /* 8 m/s ~ 30 km/h */
            basic.ground_speed > fixed_int_constant(8)) {
          const auto sc = basic.track.Reciprocal().SinCos();
          x = sc.first;
          y = sc.second;
        }
      } else if (settings_map.map_shift_bias == MAP_SHIFT_BIAS_TARGET) {
        if (calculated.task_stats.current_leg.solution_remaining.IsDefined()) {
          const auto sc =calculated.task_stats.current_leg.solution_remaining
            .vector.bearing.Reciprocal().SinCos();
          x = sc.first;
          y = sc.second;
        }
      }
      fixed position_factor = fixed(50 - settings_map.glider_screen_position) / 100;
      offset.x = PixelScalar(x * (rc.right - rc.left) * position_factor);
      offset.y = PixelScalar(y * (rc.top - rc.bottom) * position_factor);
      offset_history.Add(offset);
      offset = offset_history.GetAverage();
    }
    visible_projection.SetScreenOrigin(center.x + offset.x, center.y + offset.y);
  } else
    visible_projection.SetScreenOrigin(center.x,
        ((rc.top - rc.bottom) * settings_map.glider_screen_position / 100) + rc.bottom);

  if (!IsNearSelf()) {
    /* no-op - the Projection's location is updated manually */
  } else if (InCirclingMode() && calculated.thermal_locator.estimate_valid) {
    const fixed d_t = calculated.thermal_locator.estimate_location.Distance(basic.location);
    if (!positive(d_t)) {
      SetLocationLazy(basic.location);
    } else {
      const fixed d_max = Double(visible_projection.GetMapScale());
      const fixed t = std::min(d_t, d_max)/d_t;
      SetLocation(basic.location.Interpolate(calculated.thermal_locator.estimate_location,
                                               t));
    }
  } else if (basic.location_available)
    // Pan is off
    SetLocationLazy(basic.location);

  visible_projection.UpdateScreenBounds();
}
Beispiel #21
0
bool
MapWindowProjection::WaypointInScaleFilter(const Waypoint &way_point) const
{
  return (GetMapScale() <= (way_point.is_landable() ? fixed_int_constant(20000) :
                                                      fixed_int_constant(10000)));
}