void
MapWindow::DrawTaskOffTrackIndicator(Canvas &canvas)
{
  if (Calculated().circling 
      || !Basic().location_available
      || !Basic().track_available
      || !GetMapSettings().detour_cost_markers_enabled)
    return;

  const TaskStats &task_stats = Calculated().task_stats;
  const ElementStat &current_leg = task_stats.current_leg;

  if (!task_stats.task_valid || !current_leg.location_remaining.IsValid())
    return;

  const GeoPoint target = current_leg.location_remaining;
  GeoVector vec(Basic().location, target);

  if ((Basic().track - vec.bearing).AsDelta().AbsoluteDegrees() < fixed(10))
    // insignificant error
    return;

  fixed distance_max =
    std::min(vec.distance,
             render_projection.GetScreenDistanceMeters() * fixed(0.7));

  // too short to bother
  if (distance_max < fixed(5000))
    return;

  GeoPoint start = Basic().location;
  
  canvas.Select(*look.overlay_font);
  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundTransparent();
  
  GeoPoint dloc;
  int ilast = 0;
  for (fixed d = fixed(1) / 4; d <= fixed(1); d += fixed(1) / 4) {
    dloc = FindLatitudeLongitude(start, Basic().track, distance_max * d);
    
    fixed distance0 = start.Distance(dloc);
    fixed distance1 = target.Distance(dloc);
    fixed distance = fixed(distance0 + distance1) / vec.distance;
    int idist = iround((distance - fixed(1)) * 100);
    
    if ((idist != ilast) && (idist > 0) && (idist < 1000)) {
      TCHAR Buffer[5];
      _stprintf(Buffer, _T("%d"), idist);
      RasterPoint sc = render_projection.GeoToScreen(dloc);
      PixelSize tsize = canvas.CalcTextSize(Buffer);
      canvas.DrawText(sc.x - tsize.cx / 2, sc.y - tsize.cy / 2, Buffer);
      ilast = idist;
    }
  }
}
Пример #2
0
  /**
   * Renders the AbstractAirspace on the canvas
   * @param as AbstractAirspace to render
   */
  void
  Render(const AbstractAirspace& as)
  {
    int type = as.GetType();
    if (type <= 0)
      return;

    // No intersections for this airspace
    if (m_intersections.empty())
      return;

    // Select pens and brushes
#ifndef USE_GDI
    Color color = airspace_look.colors[settings.colours[type]];
#ifdef ENABLE_OPENGL
    color = color.WithAlpha(48);
#endif
    Brush brush(color);
#else
    const Brush &brush = airspace_look.brushes[settings.brushes[type]];
    canvas.SetTextColor(LightColor(airspace_look.colors[settings.colours[type]]));
#endif

    PixelRect rcd;
    // Calculate top and bottom coordinate
    rcd.top = chart.screenY(as.GetTopAltitude(state));
    if (as.IsBaseTerrain())
      rcd.bottom = chart.screenY(fixed_zero);
    else
      rcd.bottom = chart.screenY(as.GetBaseAltitude(state));

    // Iterate through the intersections
    for (auto it = m_intersections.begin(); it != m_intersections.end(); ++it) {
      const GeoPoint p_start = it->first;
      const GeoPoint p_end = it->second;
      const fixed distance_start = start.Distance(p_start);
      const fixed distance_end = start.Distance(p_end);

      // Determine left and right coordinate
      rcd.left = chart.screenX(distance_start);
      rcd.right = chart.screenX(distance_end);

      // only one edge found, next edge must be beyond screen
      if ((rcd.left == rcd.right) && (p_start == p_end)) {
        rcd.right = chart.screenX(chart.getXmax());
      }

      // Draw the airspace
      RenderBox(rcd, brush, settings.black_outline, type);
    }
  }
Пример #3
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();
}
Пример #4
0
bool
AirspaceFilterData::Match(const GeoPoint &location,
                          const FlatProjection &projection,
                          const AbstractAirspace &as) const
{
  if (cls != AirspaceClass::AIRSPACECLASSCOUNT && as.GetType() != cls)
    return false;

  if (name_prefix != nullptr && !as.MatchNamePrefix(name_prefix))
    return false;

  if (!direction.IsNegative()) {
    const auto closest = as.ClosestPoint(location, projection);
    const auto bearing = location.Bearing(closest);
    auto direction_error = (bearing - direction).AsDelta().AbsoluteDegrees();
    if (direction_error > fixed(18))
      return false;
  }

  if (!negative(distance)) {
    const auto closest = as.ClosestPoint(location, projection);
    const auto distance = location.Distance(closest);
    if (distance > distance)
      return false;
  }

  return true;
}
Пример #5
0
void
RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection)
{
  // Coordinates of the MapWindow center
  unsigned x = projection.GetScreenWidth() / 2;
  unsigned y = projection.GetScreenHeight() / 2;
  // GeoPoint corresponding to the MapWindow center
  GeoPoint Gmid = projection.ScreenToGeo(x, y);
  // GeoPoint "next to" Gmid (depends on terrain resolution)
  GeoPoint Gneighbor = projection.ScreenToGeo(x + quantisation_pixels,
                                              y + quantisation_pixels);

  // Geographical edge length of pixel in the MapWindow center in meters
  pixel_size = fixed_sqrt_half * Gmid.Distance(Gneighbor);

  // set resolution

  fixed map_pixel_size = map.pixel_distance(Gmid, 1);
  fixed q = map_pixel_size / pixel_size;
  if (pixel_size < fixed(3000)) {
    /* round down to reduce slope shading artefacts (caused by
       RasterBuffer interpolation) */
    quantisation_effective = std::max(1, (int)q);

    if (quantisation_effective > 25)
      /* disable slope shading when zoomed in very near (not enough
         terrain resolution to make a useful slope calculation) */
      quantisation_effective = 0;
  } else
    /* disable slope shading when zoomed out very far (too tiny) */
    quantisation_effective = 0;

  height_matrix.Fill(map, projection, quantisation_pixels, true);
}
Пример #6
0
void
AirspaceDetailsWidget::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  const NMEAInfo &basic = CommonInterface::Basic();
  TCHAR buffer[64];

  AddMultiLine(airspace.GetName());

  if (!airspace.GetRadioText().empty())
    AddReadOnly(_("Radio"), nullptr, airspace.GetRadioText().c_str());

  AddReadOnly(_("Type"), nullptr, AirspaceFormatter::GetClass(airspace));

  AirspaceFormatter::FormatAltitude(buffer, airspace.GetTop());
  AddReadOnly(_("Top"), nullptr, buffer);

  AirspaceFormatter::FormatAltitude(buffer, airspace.GetBase());
  AddReadOnly(_("Base"), nullptr, buffer);

  if (warnings != nullptr) {
    const GeoPoint closest =
      airspace.ClosestPoint(basic.location, warnings->GetProjection());
    const fixed distance = closest.Distance(basic.location);

    FormatUserDistance(distance, buffer);
    AddReadOnly(_("Range"), nullptr, buffer);
  }
}
Пример #7
0
void
TaskPointRenderer::DrawIsoline(const AATPoint &tp)
{
  if (!tp.valid() || !IsTargetVisible(tp))
    return;

  AATIsolineSegment seg(tp, task_projection);
  if (!seg.IsValid())
    return;

  #define fixed_twentieth fixed(1.0 / 20.0)

  GeoPoint start = seg.Parametric(fixed_zero);
  GeoPoint end = seg.Parametric(fixed_one);

  if (m_proj.GeoToScreenDistance(start.Distance(end)) <= 2)
    return;

  RasterPoint screen[21];
  screen[0] = m_proj.GeoToScreen(start);
  screen[20] = m_proj.GeoToScreen(end);

  for (unsigned i = 1; i < 20; ++i) {
    fixed t = i * fixed_twentieth;
    GeoPoint ga = seg.Parametric(t);
    screen[i] = m_proj.GeoToScreen(ga);
  }

  canvas.Select(task_look.isoline_pen);
  canvas.SetBackgroundTransparent();
  canvas.DrawPolyline(screen, 21);
  canvas.SetBackgroundOpaque();
}
Пример #8
0
    bool update_location(const GeoPoint &location_now) {
      fixed range_now = location_now.Distance(waypoint.location);
      if (range_now < range) {
	range = range_now;
	location = location_now;
	return true;
      }
      return false;
      // TODO: or if distance from previous tp to here is greater than leg (and wasnt previously)
    }
Пример #9
0
fixed
RasterProjection::pixel_distance(const GeoPoint &location, unsigned pixels) const
{
    enum {
        /**
         * This factor is used to reduce fixed point rounding errors.
         * x_scale and y_scale are quite large numbers, and building their
         * reciprocals may lose a lot of precision.
         */
        FACTOR = 256,
    };

    Angle distance = width_to_angle(fixed_sqrt_two * FACTOR * pixels);
    GeoPoint p = GeoPoint(location.longitude + distance, location.latitude);
    fixed x = location.Distance(p);

    distance = height_to_angle(fixed_sqrt_two * FACTOR * pixels);
    p = GeoPoint(location.longitude, location.latitude + distance);
    fixed y = location.Distance(p);

    return max(x, y) / FACTOR;
}
Пример #10
0
void
AATPoint::GetTargetRangeRadial(fixed &range, fixed &radial) const
{
  const fixed oldrange = range;

  const GeoPoint fprev = GetPrevious()->GetLocationRemaining();
  const GeoPoint floc = GetLocation();
  const Angle radialraw = (floc.Bearing(GetTargetLocation()) -
      fprev.Bearing(floc)).AsBearing();

  const fixed d = floc.Distance(GetTargetLocation());
  const fixed radius = floc.Distance(GetLocationMin());
  const fixed rangeraw = min(fixed_one, d / radius);

  radial = radialraw.AsDelta().Degrees();
  const fixed rangesign = (fabs(radial) > fixed(90)) ?
      fixed_minus_one : fixed_one;
  range = rangeraw * rangesign;

  if ((oldrange == fixed_zero) && (range == fixed_zero))
    radial = fixed_zero;
}
Пример #11
0
GeoPoint
AirspaceCircle::ClosestPoint(const GeoPoint& loc) const
{
  // Calculate distance from center point
  const fixed d = loc.Distance(m_center);

  // If loc is INSIDE the circle return loc itself
  if (d <= m_radius)
    return loc;

  // Otherwise calculate point on the circle in
  // the direction from center to loc
  return m_center.IntermediatePoint(loc, m_radius);
}
Пример #12
0
RangeAndRadial
AATPoint::GetTargetRangeRadial(fixed oldrange) const
{
  const GeoPoint fprev = GetPrevious()->GetLocationRemaining();
  const GeoPoint floc = GetLocation();
  const Angle radialraw = (floc.Bearing(GetTargetLocation()) -
      fprev.Bearing(floc)).AsBearing();
  Angle radial = radialraw.AsDelta();

  fixed d = floc.Distance(GetTargetLocation());
  if (radial < -Angle::QuarterCircle() || radial > Angle::QuarterCircle())
    d = -d;

  const fixed radius = negative(d)
    ? floc.Distance(GetLocationMin())
    : floc.Distance(GetLocationMax());
  const fixed range = Clamp(d / radius, fixed(-1), fixed(1));

  if (oldrange == fixed(0) && range == fixed(0))
    radial = Angle::Zero();

  return RangeAndRadial{ range, radial };
}
Пример #13
0
void 
Airspaces::VisitIntersecting(const GeoPoint &loc, const GeoPoint &end,
                             AirspaceIntersectionVisitor& visitor) const
{
  if (empty())
    // nothing to do
    return;

  const GeoPoint c = loc.Middle(end);
  Airspace bb_target(c, task_projection);
  int projected_range = task_projection.ProjectRangeInteger(c, loc.Distance(end) / 2);
  IntersectingAirspaceVisitorAdapter adapter(loc, end, task_projection, visitor);
  airspace_tree.visit_within_range(bb_target, -projected_range, adapter);

#ifdef INSTRUMENT_TASK
  n_queries++;
#endif
}
Пример #14
0
void 
Airspaces::VisitIntersecting(const GeoPoint &loc, const GeoPoint &end,
                             AirspaceIntersectionVisitor& visitor) const
{
  if (empty()) return; // nothing to do

  FlatRay ray(task_projection.project(loc), task_projection.project(end));

  const GeoPoint c = loc.Middle(end);
  Airspace bb_target(c, task_projection);
  int mrange = task_projection.project_range(c, loc.Distance(end) / 2);
  IntersectingAirspaceVisitorAdapter adapter(loc, end, ray, visitor);
  airspace_tree.visit_within_range(bb_target, -mrange, adapter);

#ifdef INSTRUMENT_TASK
  n_queries++;
#endif
}
Пример #15
0
bool
TargetMapWindow::isClickOnTarget(const RasterPoint pc)
{
  if (task == NULL)
    return false;

  ProtectedTaskManager::Lease task_manager(*task);
  if (!task_manager->HasTarget(target_index))
    return false;

  const GeoPoint gnull(Angle::Zero(), Angle::Zero());
  const GeoPoint& t = task_manager->GetLocationTarget(target_index, gnull);

  if (t == gnull)
    return false;

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

  return false;
}
Пример #16
0
inline void
AirspaceIntersectionVisitorSlice::Render(const AbstractAirspace &as) const
{
  AirspaceClass type = as.GetType();

  // No intersections for this airspace
  if (intersections.empty())
    return;

  PixelRect rcd;
  // Calculate top and bottom coordinate
  rcd.top = chart.ScreenY(as.GetTopAltitude(state));
  if (as.IsBaseTerrain())
    rcd.bottom = chart.ScreenY(fixed(0));
  else
    rcd.bottom = chart.ScreenY(as.GetBaseAltitude(state));

  int min_x = 1024, max_x = 0;

  // Iterate through the intersections
  for (const auto &i : intersections) {
    const GeoPoint &p_start = i.first;
    const GeoPoint &p_end = i.second;

    rcd.left = chart.ScreenX(start.Distance(p_start));

    // only one edge found, next edge must be beyond screen
    if (p_start == p_end)
      rcd.right = chart.ScreenX(chart.GetXMax());
    else
      rcd.right = chart.ScreenX(start.Distance(p_end));

    if (rcd.left < min_x)
      min_x = rcd.left;

    if (rcd.right > max_x)
      max_x = rcd.right;

    // Draw the airspace
    RenderBox(rcd, type);
  }

  min_x += Layout::GetTextPadding();
  max_x -= Layout::GetTextPadding();

  /* draw the airspace name */
  const TCHAR *name = as.GetName();
  if (name != nullptr && !StringIsEmpty(name) && min_x < max_x) {
    canvas.SetBackgroundTransparent();
    canvas.SetTextColor(COLOR_BLACK);

    const unsigned max_width = max_x - min_x;

    const PixelSize name_size = canvas.CalcTextSize(name);
    const int x = unsigned(name_size.cx) >= max_width
      ? min_x
      : (min_x + max_x - name_size.cx) / 2;
    const int y = (rcd.top + rcd.bottom - name_size.cy) / 2;

    canvas.DrawClippedText(x, y, max_x - x, name);
  }
}
Пример #17
0
bool
OLCTriangle::FindClosingPairs(unsigned old_size)
{
  if (predict) {
    return closing_pairs.insert(ClosingPair(0, n_points-1));
  }

  struct TracePointNodeAccessor {
    gcc_pure
    int GetX(const TracePointNode &node) const {
      return node.point->GetFlatLocation().longitude;
    }

    gcc_pure
    int GetY(const TracePointNode &node) const {
      return node.point->GetFlatLocation().latitude;
    }
  };

  QuadTree<TracePointNode, TracePointNodeAccessor> search_point_tree;

  for (unsigned i = old_size; i < n_points; ++i) {
    TracePointNode node;
    node.point = &GetPoint(i);
    node.index = i;

    search_point_tree.insert(node);
  }

  search_point_tree.Optimise();

  bool new_pair = false;

  for (unsigned i = old_size; i < n_points; ++i) {
    TracePointNode point;
    point.point = &GetPoint(i);
    point.index = i;

    const unsigned max_range =
      trace_master.ProjectRange(GetPoint(i).GetLocation(), max_distance);

    const GeoPoint start = GetPoint(i).GetLocation();
    const int min_altitude = GetMinimumFinishAltitude(GetPoint(i));
    const int max_altitude = GetMaximumStartAltitude(GetPoint(i));

    unsigned last = 0, first = i;

    const auto visitor = [this, i, start,
                          min_altitude, max_altitude,
                          &first, &last]
      (const TracePointNode &node) {
      const SearchPoint dest = GetPoint(node.index);

      if (node.index + 2 < i &&
          GetPoint(node.index).GetIntegerAltitude() <= max_altitude &&
          start.Distance(dest.GetLocation()) <= max_distance) {
        // point i is last point
        first = std::min(node.index, first);
        last = i;
      } else if (node.index > i + 2 &&
                 GetPoint(node.index).GetIntegerAltitude() >= min_altitude &&
                 start.Distance(dest.GetLocation()) <= max_distance) {
        // point i is first point
        first = i;
        last = std::max(node.index, last);
      }
    };

    search_point_tree.VisitWithinRange(point, max_range, visitor);

    if (last != 0 && closing_pairs.insert(ClosingPair(first, last)))
      new_pair = true;
  }

  return new_pair;
}
Пример #18
0
 /**
  * distance from this to the reference
  */
 fixed distance(const GeoPoint & ref) const {
   return reference.Distance(ref);
 }
Пример #19
0
 /**
  * distance from this to the reference
  */
 fixed DistanceTo(const GeoPoint &ref) const {
   return location.Distance(ref);
 }
Пример #20
0
 NearWaypoint(const Waypoint &_waypoint, const GeoPoint& _location)
   :waypoint(_waypoint), location(_location), leg_in(0), actual_in(0) {
   range = location.Distance(waypoint.location);
 }
Пример #21
0
    NearWaypoint(const Waypoint &_waypoint, const GeoPoint& _location,
		 const NearWaypoint& previous):
      waypoint(_waypoint), location(_location) {
      range = location.Distance(waypoint.location);
      update_leg(previous);
    }
Пример #22
0
 bool operator()(const Waypoint &waypoint) {
   return location.Distance(waypoint.location) < distance;
 }
Пример #23
0
void
RasterMap::ScanLine(const GeoPoint &start, const GeoPoint &end,
                    short *buffer, unsigned size, bool interpolate) const
{
  assert(buffer != NULL);
  assert(size > 0);

  const short invalid = RasterBuffer::TERRAIN_INVALID;

  const fixed total_distance = start.Distance(end);
  if (!positive(total_distance)) {
    std::fill(buffer, buffer + size, invalid);
    return;
  }

  /* clip the line to the map bounds */

  GeoPoint clipped_start = start, clipped_end = end;
  const GeoClip clip(GetBounds());
  if (!clip.ClipLine(clipped_start, clipped_end)) {
    std::fill(buffer, buffer + size, invalid);
    return;
  }

  fixed clipped_start_distance =
    std::max(clipped_start.Distance(start), fixed(0));
  fixed clipped_end_distance =
    std::max(clipped_end.Distance(start), fixed(0));

  /* calculate the offsets of the clipped range within the buffer */

  unsigned clipped_start_offset =
    (unsigned)(size * clipped_start_distance / total_distance);
  unsigned clipped_end_offset =
    uround(size * clipped_end_distance / total_distance);
  if (clipped_end_offset > size)
    clipped_end_offset = size;
  if (clipped_start_offset + 2 > clipped_end_offset) {
    std::fill(buffer, buffer + size, invalid);
    return;
  }

  assert(clipped_start_offset < size);
  assert(clipped_end_offset <= size);

  /* fill the two regions which are outside the map  */

  std::fill(buffer, buffer + clipped_start_offset, invalid);
  std::fill(buffer + clipped_end_offset, buffer + size, invalid);

  /* now scan the middle part which is within the map */

  const unsigned max_x = raster_tile_cache.GetFineWidth();
  const unsigned max_y = raster_tile_cache.GetFineHeight();

  RasterLocation raster_start = projection.ProjectFine(clipped_start);
  if (raster_start.x >= max_x)
    raster_start.x = max_x - 1;
  if (raster_start.y >= max_y)
    raster_start.y = max_y - 1;

  RasterLocation raster_end = projection.ProjectFine(clipped_end);
  if (raster_end.x >= max_x)
    raster_end.x = max_x - 1;
  if (raster_end.y >= max_y)
    raster_end.y = max_y - 1;

  raster_tile_cache.ScanLine(raster_start, raster_end,
                             buffer + clipped_start_offset,
                             clipped_end_offset - clipped_start_offset,
                             interpolate);
}
Пример #24
0
bool 
AirspaceCircle::Inside(const GeoPoint &loc) const
{
  return (loc.Distance(m_center) <= m_radius);
}