Пример #1
0
void MapWindow::MapWaypointLabelSortAndRender(Canvas &canvas) {
  qsort(&MapWaypointLabelList,
        MapWaypointLabelListCount,
        sizeof(MapWaypointLabel_t),
        MapWaypointLabelListCompare);

  // now draw task/landable waypoints in order of range (closest last)
  // writing unconditionally
  for (int j = MapWaypointLabelListCount - 1; j >= 0; j--){
    MapWaypointLabel_t *E = &MapWaypointLabelList[j];
    // draws if they are in task unconditionally,
    // otherwise, does comparison
    if (E->inTask) {
      TextInBox(canvas, E->Name, E->Pos.x,
                E->Pos.y, E->Mode, MapRect,
                NULL);
    }
  }

  // now draw normal waypoints in order of range (furthest away last)
  // without writing over each other (or the task ones)
  for (unsigned i = 0; i < MapWaypointLabelListCount; i++) {
    MapWaypointLabel_t *E = &MapWaypointLabelList[i];
    if (!E->inTask) {
      TextInBox(canvas, E->Name, E->Pos.x,
                E->Pos.y, E->Mode, MapRect, &label_block);
    }
  }
}
Пример #2
0
void MapWindow::DrawCpuStats(HDC hdc, RECT rc) {

  if (Appearance.InverseInfoBox == true) return;

  TCHAR Buffer[LKSIZEBUFFERLARGE];
  TextInBoxMode_t TextDisplayMode = {0};
  TextDisplayMode.Color = RGB_WHITE;
  TextDisplayMode.WhiteBorder = 1; // inside a white circle
  TextDisplayMode.Border = 1;      // add a black border to the circle

#if (WINDOWSPC>0)
  wsprintf(Buffer,_T("CPU Draw=%d Calc=%d us"), Cpu_Draw, Cpu_Calc);
#else
  wsprintf(Buffer,_T("CPU Draw=%d Calc=%d ms"), Cpu_Draw, Cpu_Calc);
#endif
  TextInBox(hdc, &rc, Buffer, 000, 200 , 0, &TextDisplayMode, false);
#if (WINDOWSPC>0)
  wsprintf(Buffer,_T("CPU Inst=%d PortA=%d PortB=%d us"), Cpu_Instrument, Cpu_PortA, Cpu_PortB);
#else
  wsprintf(Buffer,_T("CPU Inst=%d PortA=%d PortB=%d ms"), Cpu_Instrument, Cpu_PortA, Cpu_PortB);
#endif
  TextInBox(hdc, &rc, Buffer, 000, 240 , 0, &TextDisplayMode, false);

  //wsprintf(Buffer,_T("Landsc=%d Geom=%d"), InfoBoxLayout::landscape, InfoBoxLayout::InfoBoxGeometry);
  //TextInBox(hdc, Buffer, 000, 280 , 0, TextDisplayMode, false);
  //wsprintf(Buffer,_T("Recents=%d"), RecentNumber);
  //TextInBox(hdc, Buffer, 000, 280 , 0, TextDisplayMode, false);

}
Пример #3
0
void
GlueMapWindow::DrawPanInfo(Canvas &canvas) const
{
  GeoPoint location = render_projection.GetGeoLocation();

  TextInBoxMode mode;
  mode.mode = RenderMode::RM_OUTLINED_INVERTED;
  mode.bold = true;
  mode.align = A_RIGHT;

  UPixelScalar padding = Layout::FastScale(4);
  UPixelScalar height = Fonts::map_bold.GetHeight();
  PixelScalar y = 0 + padding;
  PixelScalar x = render_projection.GetScreenWidth() - padding;

  if (terrain) {
    short elevation = terrain->GetTerrainHeight(location);
    if (!RasterBuffer::IsSpecial(elevation)) {
      StaticString<64> elevation_short, elevation_long;
      FormatUserAltitude(fixed(elevation),
                                elevation_short.buffer(), elevation_short.MAX_SIZE);

      elevation_long = _("Elevation: ");
      elevation_long += elevation_short;

      TextInBox(canvas, elevation_long, x, y, mode,
                render_projection.GetScreenWidth(),
                render_projection.GetScreenHeight());

      y += height;
    }
  }

  TCHAR buffer[256];
  FormatGeoPoint(location, buffer, ARRAY_SIZE(buffer), _T('\n'));

  TCHAR *start = buffer;
  while (true) {
    TCHAR *newline = _tcschr(start, _T('\n'));
    if (newline != NULL)
      *newline = _T('\0');

    TextInBox(canvas, start, x, y, mode,
              render_projection.GetScreenWidth(),
              render_projection.GetScreenHeight());

    y += height;

    if (newline == NULL)
      break;

    start = newline + 1;
  }
}
Пример #4
0
void MapWindow::DrawDebug(HDC hdc, RECT rc) {

  TCHAR Buffer[LKSIZEBUFFERLARGE];
  TextInBoxMode_t TextDisplayMode = {0};
  TextDisplayMode.Color = RGB_WHITE;
  TextDisplayMode.WhiteBorder = 1; // inside a white circle
  TextDisplayMode.Border = 1;      // add a black border to the circle

  _stprintf(Buffer,_T("ModeIndex=%d CURTYPE=%d MSM=%d"), ModeIndex, ModeType[ModeIndex],MapSpaceMode );
  TextInBox(hdc, &rc, Buffer, 000, 200 , 0, &TextDisplayMode, false);
  _stprintf(Buffer,_T("MTableTop=%d ModeTable=%d=MSM"), ModeTableTop[ModeIndex], ModeTable[ModeIndex][ModeType[ModeIndex]] );
  TextInBox(hdc, &rc, Buffer, 000, 240 , 0, &TextDisplayMode, false);

}
Пример #5
0
void
GlueMapWindow::DrawGPSStatus(Canvas &canvas, const PixelRect &rc,
                             const NMEAInfo &info) const
{
  const TCHAR *txt;
  MaskedIcon *icon = NULL;

  if (!info.connected) {
    icon = &Graphics::hGPSStatus2;
    txt = _("GPS not connected");
  } else if (!info.location_available) {
    icon = &Graphics::hGPSStatus1;
    txt = _("GPS waiting for fix");
  } else {
    return; // early exit
  }

  int x = rc.left + Layout::FastScale(2);
  int y = rc.bottom - Layout::FastScale(35);
  icon->draw(canvas, x, y);

  x += icon->get_size().cx + Layout::FastScale(4);
  y = rc.bottom - Layout::FastScale(34);

  TextInBoxMode mode;
  mode.Mode = RoundedBlack;
  mode.Bold = true;

  TextInBox(canvas, txt, x, y, mode, rc, NULL);
}
Пример #6
0
void
WindArrowRenderer::Draw(Canvas &canvas, const Angle screen_angle,
                        const SpeedVector wind, const PixelPoint pos,
                        const PixelRect rc, WindArrowStyle arrow_style)
{
  // Draw arrow (and tail)

  const unsigned length = uround(Quadruple(wind.norm));
  DrawArrow(canvas, pos, wind.bearing - screen_angle, length, arrow_style);

  // Draw wind speed label

  StaticString<12> buffer;
  buffer.Format(_T("%i"), iround(Units::ToUserWindSpeed(wind.norm)));

  canvas.SetTextColor(COLOR_BLACK);
  canvas.Select(*look.font);

  const unsigned offset = uround(M_SQRT2 * wind.norm);
  BulkPixelPoint label[] = {
    { 18, -26 - int(offset) },
  };
  PolygonRotateShift(label, ARRAY_SIZE(label),
                     pos, wind.bearing - screen_angle);

  TextInBoxMode style;
  style.align = TextInBoxMode::Alignment::CENTER;
  style.vertical_position = TextInBoxMode::VerticalPosition::CENTERED;
  style.shape = LabelShape::OUTLINED;

  TextInBox(canvas, buffer, label[0].x, label[0].y, style, rc);
}
Пример #7
0
void MapWindow::DrawGPSStatus(Canvas &canvas, const RECT rc)
{

  if (Basic().Connected
      && !Basic().NAVWarning
      && Basic().SatellitesUsed)
    // nothing to do, all OK
    return;

  TCHAR gpswarningtext1[] = TEXT("GPS not connected");
  TCHAR gpswarningtext2[] = TEXT("GPS waiting for fix");
  TextInBoxMode_t TextInBoxMode = {2};
  TCHAR *txt=NULL;
  Bitmap *bmp=NULL;

  if (!Basic().Connected) {
    bmp = &MapGfx.hGPSStatus2;
    txt = gpswarningtext1;
  } else
    if (Basic().NAVWarning || (Basic().SatellitesUsed == 0)) {
      bmp = &MapGfx.hGPSStatus2;
      txt = gpswarningtext2;
    } else {
      return; // early exit
    }
  draw_bitmap(canvas, *bmp,
	      rc.left + IBLSCALE(2),
	      rc.bottom +IBLSCALE(Appearance.GPSStatusOffset.y - 22),
	      0, 0, 20, 20, false);
  TextInBox(canvas, gettext(txt),
	    rc.left+IBLSCALE(24),
	    rc.bottom+IBLSCALE(Appearance.GPSStatusOffset.y-19),
	    TextInBoxMode, rc);
}
Пример #8
0
void
GlueMapWindow::DrawGPSStatus(Canvas &canvas, const PixelRect &rc,
                             const NMEAInfo &info) const
{
  const TCHAR *txt;
  const MaskedIcon *icon;

  if (!info.alive) {
    icon = &look.no_gps_icon;
    txt = _("GPS not connected");
  } else if (!info.location_available) {
    icon = &look.waiting_for_fix_icon;
    txt = _("GPS waiting for fix");
  } else
    // early exit
    return;

  PixelScalar x = rc.left + Layout::FastScale(2);
  PixelScalar y = rc.bottom - Layout::FastScale(35);
  icon->Draw(canvas, x, y);

  x += icon->GetSize().cx + Layout::FastScale(4);
  y = rc.bottom - Layout::FastScale(34);

  TextInBoxMode mode;
  mode.shape = LabelShape::ROUNDED_BLACK;

  const Font &font = *look.overlay_font;
  canvas.Select(font);
  TextInBox(canvas, txt, x, y, mode, rc, nullptr);
}
Пример #9
0
static void
MapWaypointLabelRender(Canvas &canvas, UPixelScalar width, UPixelScalar height,
                       LabelBlock &label_block,
                       WaypointLabelList &labels)
{
  labels.Sort();

  for (const auto &l : labels) {
    canvas.Select(l.bold ? Fonts::map_bold : Fonts::map);

    TextInBox(canvas, l.Name, l.Pos.x, l.Pos.y, l.Mode,
              width, height, &label_block);
  }
}
Пример #10
0
bool
TextInBox(Canvas &canvas, const TCHAR *Value, int x, int y,
          TextInBoxMode_t Mode,
          unsigned screen_width, unsigned screen_height,
          LabelBlock *label_block)
{
  PixelRect rc;
  rc.left = 0;
  rc.top = 0;
  rc.right = screen_width;
  rc.bottom = screen_height;

  return TextInBox(canvas, Value, x, y, Mode, rc, label_block);
}
Пример #11
0
static void
MapWaypointLabelRender(Canvas &canvas, unsigned width, unsigned height,
                       LabelBlock &label_block,
                       WaypointLabelList &labels,
                       const WaypointLook &look)
{
  labels.Sort();

  for (const auto &l : labels) {
    canvas.Select(l.bold ? *look.bold_font : *look.font);

    TextInBox(canvas, l.Name, l.Pos.x, l.Pos.y, l.Mode,
              width, height, &label_block);
  }
}
Пример #12
0
// LK Status message
void MapWindow::DrawLKStatus(HDC hdc, RECT rc) {

  TextInBoxMode_t TextDisplayMode = {0};
  TCHAR Buffer[LKSIZEBUFFERLARGE];

  short bottomlines;
  short middlex=(rc.right-rc.left)/2;
  short left=rc.left+NIBLSCALE(5);
  short contenttop=rc.top+NIBLSCALE(50);

  TextDisplayMode.Color = RGB_BLACK;
  TextDisplayMode.NoSetFont = 1;
  //TextDisplayMode.AlligneRight = 0;
  TextDisplayMode.AlligneCenter = 1;
  TextDisplayMode.WhiteBold = 1;
  TextDisplayMode.Border = 1;
  // HFONT oldfont=(HFONT)Surface.SelectObject(LK8PanelBigFont);

  switch(ModeIndex) {
	case LKMODE_MAP:
		_stprintf(Buffer,TEXT("MAP mode, 1 of 1"));
		break;
	case LKMODE_INFOMODE:
		_stprintf(Buffer,TEXT("%d-%d"), ModeIndex,CURTYPE+1);
		break;
	case LKMODE_WP:
		_stprintf(Buffer,TEXT("%d-%d"), ModeIndex,CURTYPE+1);
		break;
	case LKMODE_NAV:
		_stprintf(Buffer,TEXT("%d-%d"), ModeIndex,CURTYPE+1);
		break;
	default:
		_stprintf(Buffer,TEXT("UNKOWN mode"));
		break;
  }
  TextInBox(hdc, &rc, Buffer, middlex, 200 , 0, &TextDisplayMode, false);

  //Surface.SelectObject(oldfont);
  return;
}
Пример #13
0
void
GlueMapWindow::DrawPanInfo(Canvas &canvas) const
{
  if (!render_projection.IsValid())
    return;

  GeoPoint location = render_projection.GetGeoLocation();

  TextInBoxMode mode;
  mode.shape = LabelShape::OUTLINED;
  mode.align = TextInBoxMode::Alignment::RIGHT;

  const Font &font = *look.overlay_font;
  canvas.Select(font);

  UPixelScalar padding = Layout::FastScale(4);
  UPixelScalar height = font.GetHeight();
  PixelScalar y = 0 + padding;
  PixelScalar x = render_projection.GetScreenWidth() - padding;

  if (compass_visible)
    /* don't obscure the north arrow */
    /* TODO: obtain offset from CompassRenderer */
    y += Layout::Scale(19) + Layout::FastScale(13);

  if (terrain) {
    short elevation = terrain->GetTerrainHeight(location);
    if (!RasterBuffer::IsSpecial(elevation)) {
      StaticString<64> elevation_short, elevation_long;
      FormatUserAltitude(fixed(elevation),
                                elevation_short.buffer(), elevation_short.MAX_SIZE);

      elevation_long = _("Elevation: ");
      elevation_long += elevation_short;

      TextInBox(canvas, elevation_long, x, y, mode,
                render_projection.GetScreenWidth(),
                render_projection.GetScreenHeight());

      y += height;
    }
  }

  TCHAR buffer[256];
  FormatGeoPoint(location, buffer, ARRAY_SIZE(buffer), _T('\n'));

  TCHAR *start = buffer;
  while (true) {
    TCHAR *newline = _tcschr(start, _T('\n'));
    if (newline != nullptr)
      *newline = _T('\0');

    TextInBox(canvas, start, x, y, mode,
              render_projection.GetScreenWidth(),
              render_projection.GetScreenHeight());

    y += height;

    if (newline == nullptr)
      break;

    start = newline + 1;
  }
}
Пример #14
0
void MapWindow::DrawFinalGlide(Canvas &canvas, const RECT rc)
{

  /*
  POINT Scale[18] = {
    {5,-50 }, {14,-60 }, {23, -50},
    {5,-40 }, {14,-50 }, {23, -40},
    {5,-30 }, {14,-40 }, {23, -30},
    {5,-20 }, {14,-30 }, {23, -20},
    {5,-10 }, {14,-20 }, {23, -10},
    {5, 0  }, {14,-10 }, {23,   0},
  };*/

  POINT GlideBar[6] =
    { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };
  POINT GlideBar0[6] =
    { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };

  TCHAR Value[10];

  int Offset;
  int Offset0;
  int i;

  if (task.Valid()){

    const int y0 = ( (rc.bottom - rc.top )/2)+rc.top;

    // 60 units is size, div by 8 means 60*8 = 480 meters.

    Offset = ((int)Calculated().TaskAltitudeDifference)/8;
    Offset0 = ((int)Calculated().TaskAltitudeDifference0)/8;
    // TODO feature: should be an angle if in final glide mode

    if(Offset > 60) Offset = 60;
    if(Offset < -60) Offset = -60;
    Offset = IBLSCALE(Offset);
    if(Offset<0) {
      GlideBar[1].y = IBLSCALE(9);
    }

    if(Offset0 > 60) Offset0 = 60;
    if(Offset0 < -60) Offset0 = -60;
    Offset0 = IBLSCALE(Offset0);
    if(Offset0<0) {
      GlideBar0[1].y = IBLSCALE(9);
    }

    for(i=0;i<6;i++)
    {
      GlideBar[i].y += y0;
      GlideBar[i].x = IBLSCALE(GlideBar[i].x)+rc.left;
    }
    GlideBar[0].y -= Offset;
    GlideBar[1].y -= Offset;
    GlideBar[2].y -= Offset;

    for(i=0;i<6;i++)
    {
      GlideBar0[i].y += y0;
      GlideBar0[i].x = IBLSCALE(GlideBar0[i].x)+rc.left;
    }
    GlideBar0[0].y -= Offset0;
    GlideBar0[1].y -= Offset0;
    GlideBar0[2].y -= Offset0;

    if ((Offset<0)&&(Offset0<0)) {
      // both below
      if (Offset0!= Offset) {
        int dy = (GlideBar0[0].y-GlideBar[0].y)
          +(GlideBar0[0].y-GlideBar0[3].y);
        dy = max(IBLSCALE(3), dy);
        GlideBar[3].y = GlideBar0[0].y-dy;
        GlideBar[4].y = GlideBar0[1].y-dy;
        GlideBar[5].y = GlideBar0[2].y-dy;

        GlideBar0[0].y = GlideBar[3].y;
        GlideBar0[1].y = GlideBar[4].y;
        GlideBar0[2].y = GlideBar[5].y;
      } else {
        Offset0 = 0;
      }

    } else if ((Offset>0)&&(Offset0>0)) {
      // both above
      GlideBar0[3].y = GlideBar[0].y;
      GlideBar0[4].y = GlideBar[1].y;
      GlideBar0[5].y = GlideBar[2].y;

      if (abs(Offset0-Offset)<IBLSCALE(4)) {
        Offset= Offset0;
      }
    }

    // draw actual glide bar
    if (Offset<=0) {
      if (Calculated().LandableReachable) {
        canvas.select(MapGfx.hpFinalGlideBelowLandable);
        canvas.select(MapGfx.hbFinalGlideBelowLandable);
      } else {
        canvas.select(MapGfx.hpFinalGlideBelow);
        canvas.select(MapGfx.hbFinalGlideBelow);
      }
    } else {
      canvas.select(MapGfx.hpFinalGlideAbove);
      canvas.select(MapGfx.hbFinalGlideAbove);
    }
    canvas.polygon(GlideBar, 6);

    // draw glide bar at mc 0
    if (Offset0<=0) {
      if (Calculated().LandableReachable) {
        canvas.select(MapGfx.hpFinalGlideBelowLandable);
        canvas.hollow_brush();
      } else {
        canvas.select(MapGfx.hpFinalGlideBelow);
        canvas.hollow_brush();
      }
    } else {
      canvas.select(MapGfx.hpFinalGlideAbove);
      canvas.hollow_brush();
    }
    if (Offset!=Offset0) {
      canvas.polygon(GlideBar0, 6);
    }

    // JMW draw x on final glide bar if unreachable at current Mc
    // hpAircraftBorder
    if ((Calculated().TaskTimeToGo>0.9*ERROR_TIME)
        || ((GlidePolar::GetMacCready()<0.01)
            && (Calculated().TaskAltitudeDifference<0))) {
      canvas.select(MapGfx.hpAircraftBorder);
      POINT Cross[4] = { {-5, -5},
                         { 5,  5},
                         {-5,  5},
                         { 5, -5} };
      for (i=0; i<4; i++) {
        Cross[i].x = IBLSCALE(Cross[i].x+9);
        Cross[i].y = IBLSCALE(Cross[i].y+9)+y0;
      }
      canvas.polygon(Cross, 2);
      canvas.polygon(&Cross[2], 2);
    }

    if (Appearance.IndFinalGlide == fgFinalGlideDefault){

      _stprintf(Value,TEXT("%1.0f "),
                ALTITUDEMODIFY*Calculated().TaskAltitudeDifference);

      if (Offset>=0) {
        Offset = GlideBar[2].y+Offset+IBLSCALE(5);
      } else {
        if (Offset0>0) {
          Offset = GlideBar0[1].y-IBLSCALE(15);
        } else {
          Offset = GlideBar[2].y+Offset-IBLSCALE(15);
        }
      }

      TextInBoxMode_t TextInBoxMode = {1|8};
      TextInBox(canvas, Value, 0, (int)Offset, TextInBoxMode, rc);

    } else
      if (Appearance.IndFinalGlide == fgFinalGlideAltA){

        SIZE  TextSize;
        int y = GlideBar[3].y;
        // was ((rc.bottom - rc.top )/2)-rc.top-
        //            Appearance.MapWindowBoldFont.CapitalHeight/2-1;
        int x = GlideBar[2].x+IBLSCALE(1);
        const Bitmap *Bmp;
        POINT  BmpPos;
        POINT  BmpSize;

        _stprintf(Value, TEXT("%1.0f"),
                  Units::ToUserAltitude(Calculated().TaskAltitudeDifference));

        canvas.select(MapWindowBoldFont);
        TextSize = canvas.text_size(Value);

        canvas.white_brush();
        canvas.white_pen();
        canvas.rectangle(x, y,
                         x + IBLSCALE(1) + TextSize.cx,
                         y + Appearance.MapWindowBoldFont.CapitalHeight +
                         IBLSCALE(2));

        canvas.text(x + IBLSCALE(1),
                    y + Appearance.MapWindowBoldFont.CapitalHeight -
                    Appearance.MapWindowBoldFont.AscentHeight +
                    IBLSCALE(1),
                    Value);

        if (Units::GetUnitBitmap(Units::GetUserAltitudeUnit(),
                                 &Bmp, &BmpPos, &BmpSize, 0)){
          draw_bitmap(canvas, *Bmp,
                      x + TextSize.cx + IBLSCALE(1), y,
                      BmpPos.x, BmpPos.y,
                      BmpSize.x, BmpSize.y, false);
        }
      }
  }
}
Пример #15
0
void MapWindow::DrawWindAtAircraft2(Canvas &canvas, const POINT Orig, const RECT rc) {
  int i;
  POINT Start;
  TCHAR sTmp[12];
  static SIZE tsize = {0,0};

  if (Calculated().WindSpeed<1) {
    return; // JMW don't bother drawing it if not significant
  }

  if (tsize.cx == 0){
    canvas.select(MapWindowBoldFont);
    tsize = canvas.text_size(TEXT("99"));
    tsize.cx = tsize.cx/2;
  }

  canvas.select(MapGfx.hpWind);
  canvas.select(MapGfx.hbWind);

  int wmag = iround(4.0*Calculated().WindSpeed);

  Start.y = Orig.y;
  Start.x = Orig.x;

  int kx = tsize.cx/InfoBoxLayout::scale/2;

  POINT Arrow[7] = { {0,-20}, {-6,-26}, {0,-20},
                     {6,-26}, {0,-20},
                     {8+kx, -24},
                     {-8-kx, -24}};

  for (i=1;i<4;i++)
    Arrow[i].y -= wmag;

  PolygonRotateShift(Arrow, 7, Start.x, Start.y,
		     Calculated().WindBearing-DisplayAngle);
  canvas.polygon(Arrow, 5);

  if (SettingsMap().WindArrowStyle==1) {
    POINT Tail[2] = {{0,-20}, {0,-26-min(20,wmag)*3}};
    double angle = AngleLimit360(Calculated().WindBearing-DisplayAngle);
    for(i=0; i<2; i++) {
      if (InfoBoxLayout::scale>1) {
        Tail[i].x *= InfoBoxLayout::scale;
        Tail[i].y *= InfoBoxLayout::scale;
      }
      protateshift(Tail[i], angle, Start.x, Start.y);
    }

    // optionally draw dashed line
    Pen dash_pen(Pen::DASH, 1, Color(0, 0, 0));
    canvas.select(dash_pen);
    canvas.line(Tail[0], Tail[1]);
  }


  _stprintf(sTmp, TEXT("%i"), iround(Calculated().WindSpeed * SPEEDMODIFY));

  TextInBoxMode_t TextInBoxMode = { 16 | 32 }; // JMW test {2 | 16};
  if (Arrow[5].y>=Arrow[6].y) {
    TextInBox(canvas, sTmp, Arrow[5].x-kx, Arrow[5].y, TextInBoxMode, rc);
  } else {
    TextInBox(canvas, sTmp, Arrow[6].x-kx, Arrow[6].y, TextInBoxMode, rc);
  }
}
Пример #16
0
void
FinalGlideBarRenderer::Draw(Canvas &canvas, const PixelRect &rc,
                            const DerivedInfo &calculated,
                            const GlideSettings &glide_settings,
                            const bool final_glide_bar_mc0_enabled) const
{
#ifdef ENABLE_OPENGL
  const GLEnable blend(GL_BLEND);
#endif

  RasterPoint GlideBar[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint GlideBar0[4] = {
      { 0, 0 }, { 9, -9 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint clipping_arrow[6] = {
      { 0, 0 }, { 9, 9 }, { 18, 0 }, { 18, 6 }, { 9, 15 }, { 0, 6 }
  };
  RasterPoint clipping_arrow0[4] = {
      { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 }
  };

  TCHAR Value[10];

  const TaskStats &task_stats = calculated.task_stats;
  const ElementStat &total = task_stats.total;
  const GlideResult &solution = total.solution_remaining;
  const GlideResult &solution_mc0 = total.solution_mc0;

  if (!task_stats.task_valid || !solution.IsOk() || !solution_mc0.IsDefined())
    return;

  const int y0 = (rc.bottom + rc.top) / 2;

  PixelScalar dy_glidebar = 0;
  PixelScalar dy_glidebar0 = 0;

  FormatUserAltitude(solution.SelectAltitudeDifference(glide_settings),
                            Value, false);
  canvas.Select(*look.font);
  const PixelSize text_size = canvas.CalcTextSize(Value);

  PixelScalar clipping_arrow_offset = Layout::Scale(4);
  PixelScalar clipping_arrow0_offset = Layout::Scale(4);

  // 468 meters is it's size. Will be divided by 9 to fit screen resolution.
  int altitude_difference = (int)
    solution.SelectAltitudeDifference(glide_settings);
  int altitude_difference0 = (int)
    solution_mc0.SelectAltitudeDifference(glide_settings);
  // TODO feature: should be an angle if in final glide mode

  // cut altitude_difference at +- 468 meters (55 units)
  if (altitude_difference > 468)
    altitude_difference = 468;
  if (altitude_difference < -468)
    altitude_difference = -468;

  // 55 units is size, 468 meters div by 9 means 55.
  int Offset = altitude_difference / 9;
  
  Offset = Layout::Scale(Offset);
  if (altitude_difference <= 0) {
    GlideBar[1].y = Layout::Scale(9);
    dy_glidebar = text_size.cy + 2;
  } else {
    GlideBar[1].y = -Layout::Scale(9);
    clipping_arrow[1].y = -clipping_arrow[1].y;
    clipping_arrow[3].y = -clipping_arrow[3].y;
    clipping_arrow[4].y = -clipping_arrow[4].y;
    clipping_arrow[5].y = -clipping_arrow[5].y;
    clipping_arrow_offset = -clipping_arrow_offset;
    dy_glidebar = -1;
  }

  // cut altitude_difference0 at +- 468 meters (55 units)
  if (altitude_difference0 > 468)
    altitude_difference0 = 468;
  if (altitude_difference0 < -468)
    altitude_difference0 = -468;

  // 55 units is size, therefore div by 9.
  int Offset0 = altitude_difference0 / 9;
  
  Offset0 = Layout::Scale(Offset0);
  if (altitude_difference0 <= 0) {
    GlideBar0[1].y = Layout::Scale(9);
    dy_glidebar0 = text_size.cy + 2;
  } else {
    GlideBar0[1].y = -Layout::Scale(9);
    clipping_arrow0[1].y = -clipping_arrow0[1].y;
    clipping_arrow0[2].y = -clipping_arrow0[2].y;
    clipping_arrow0[3].y = -clipping_arrow0[3].y;
    clipping_arrow0_offset = -clipping_arrow0_offset;
    dy_glidebar0 = -1;
  }

  for (unsigned i = 0; i < 6; i++) {
    GlideBar[i].y += y0 + dy_glidebar;
    GlideBar[i].x = Layout::Scale(GlideBar[i].x) + rc.left;
  }

  GlideBar[0].y -= Offset;
  GlideBar[1].y -= Offset;
  GlideBar[2].y -= Offset;

  for (unsigned i = 0; i < 4; i++) {
    GlideBar0[i].y += y0 + dy_glidebar0;
    GlideBar0[i].x = Layout::Scale(GlideBar0[i].x) + rc.left;
  }

  GlideBar0[0].y -= Offset0;
  GlideBar0[1].y -= Offset0;

  if ((altitude_difference0 >= altitude_difference) && (altitude_difference > 0)) {
    // both above and mc0 arrow larger than mc arrow
    GlideBar0[2].y = GlideBar[1].y;    // both below
    GlideBar0[3].y = GlideBar[0].y;
  }

  // prepare clipping arrow
  for (unsigned i = 0; i < 6; i++) {
    clipping_arrow[i].y = Layout::Scale(clipping_arrow[i].y) + y0 - Offset
      + clipping_arrow_offset + dy_glidebar;
    clipping_arrow[i].x = Layout::Scale(clipping_arrow[i].x) + rc.left;
  }

  // prepare clipping arrow mc0
  for (unsigned i = 0; i < 4; i++) {
    clipping_arrow0[i].y = Layout::Scale(clipping_arrow0[i].y) + y0 - Offset0
      + clipping_arrow0_offset + dy_glidebar0;
    clipping_arrow0[i].x = Layout::Scale(clipping_arrow0[i].x) + rc.left;
  }

  // draw actual glide bar
  if (altitude_difference <= 0) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.pen_below_landable);
      canvas.Select(look.brush_below_landable);
    } else {
      canvas.Select(look.pen_below);
      canvas.Select(look.brush_below);
    }
  } else {
    canvas.Select(look.pen_above);
    canvas.Select(look.brush_above);
  }
  canvas.DrawPolygon(GlideBar, 6);

  // draw clipping arrow
  if ((altitude_difference <= -468 ) || (altitude_difference >= 468))
    canvas.DrawPolygon(clipping_arrow, 6);

  // draw glide bar at mc 0
  if (altitude_difference0 <= 0 && final_glide_bar_mc0_enabled) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.pen_below_landable);
      canvas.Select(look.brush_below_landable_mc0);
    } else {
      canvas.Select(look.pen_below);
      canvas.Select(look.brush_below_mc0);
    }
  } else {
    canvas.Select(look.pen_above);
    canvas.Select(look.brush_above_mc0);
  }

  if ( ( (altitude_difference != altitude_difference0) || (altitude_difference0 < 0) )
      && final_glide_bar_mc0_enabled) {
    canvas.DrawPolygon(GlideBar0, 4);

    if ((altitude_difference0 <= -468 ) || (altitude_difference0 >= 468))
      canvas.DrawPolygon(clipping_arrow0, 4);
  }

  // draw cross (x) on final glide bar if unreachable at current Mc
  // or above final glide but impeded by obstacle
  int cross_sign = 0;

  if (!total.IsAchievable())
    cross_sign = 1;
  if (calculated.terrain_warning && (altitude_difference>0))
    cross_sign = -1;

  if (cross_sign != 0) {
    canvas.Select(task_look.bearing_pen);
    canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 - 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 + 5));
    canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 + 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 - 5));
  }

  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundColor(COLOR_WHITE);

  TextInBoxMode style;
  style.shape = LabelShape::ROUNDED_BLACK;
  style.move_in_view = true;

  if (text_size.cx < Layout::Scale(18)) {
    style.align = TextInBoxMode::Alignment::RIGHT;
    TextInBox(canvas, Value, Layout::Scale(18), y0, style, rc);
  } else
    TextInBox(canvas, Value, 0, y0, style, rc);

}
Пример #17
0
void
VarioBarRenderer::Draw(Canvas &canvas, const PixelRect &rc,
                            const MoreData &basic,
                            const DerivedInfo &calculated,
                            const GlidePolar &glide_polar,
                            const bool vario_bar_avg_enabled) const
{
#ifdef ENABLE_OPENGL
  const ScopeAlphaBlend alpha_blend;
#endif

  RasterPoint VarioBar[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint VarioBarAvg[4] = {
      { 0, 0 }, { 9, -9 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint clipping_arrow[6] = {
      { 0, 0 }, { 9, 9 }, { 18, 0 }, { 18, 6 }, { 9, 15 }, { 0, 6 }
  };
  RasterPoint clipping_arrow_av[4] = {
      { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 }
  };
  RasterPoint mc_arrow[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, -2 }, { 9, -11 }, { 0, -2 }
  };

  TCHAR Value[10];

  const int y0 = (rc.bottom + rc.top) / 2;

  /* NOTE: size_divisor replaces the fixed value 9 that was used throughout
   * the code sink which caused fixed size rendering regardless of
   * map size (except the effects of Layout::Scale()). This method
   * is not usable with variable map sizes (e.g. because of the cross-section
   * area). size_divisor is used to introduce a screen size dependent scaling.
   * That workaround is an ugly hack and needs a rework. */
  const auto size_divisor =
    std::max((fixed) Layout::Scale(70 / (rc.bottom - rc.top)), fixed(0.15));

  PixelScalar dy_variobar = 0;
  PixelScalar dy_variobar_av = 0;
  PixelScalar dy_variobar_mc = 0;

  PixelScalar clipping_arrow_offset = Layout::Scale(4);
  PixelScalar clipping_arrow_av_offset = Layout::Scale(4);
//  PixelScalar clipping_arrow_mc_offset = Layout::Scale(4);

  auto vario_gross = basic.brutto_vario;

  FormatUserVerticalSpeed(vario_gross, Value, false, true);
  canvas.Select(*look.font);
  const PixelSize text_size = canvas.CalcTextSize(Value);

  auto vario_avg = calculated.average;

  // cut vario_gross at +- 5 meters/s
  if (vario_gross > fixed(5))
    vario_gross = fixed(5);
  if (vario_gross < fixed(-5))
    vario_gross = fixed(-5);

  int Offset = (int)(vario_gross / size_divisor);

  Offset = Layout::Scale(Offset);
  if (!positive(vario_gross)) {
    VarioBar[1].y = Layout::Scale(9);
    dy_variobar = text_size.cy + 2;
  } else {
    VarioBar[1].y = -Layout::Scale(9);
    clipping_arrow[1].y = -clipping_arrow[1].y;
    clipping_arrow[3].y = -clipping_arrow[3].y;
    clipping_arrow[4].y = -clipping_arrow[4].y;
    clipping_arrow[5].y = -clipping_arrow[5].y;
    clipping_arrow_offset = -clipping_arrow_offset;
    dy_variobar = -1;
  }

  // cut vario_avg at +- 5 meters/s
  if (vario_avg > fixed(5))
    vario_avg = fixed(5);
  if (vario_avg < fixed(-5))
    vario_avg = fixed(-5);

  int OffsetAvg = int(vario_avg / size_divisor);

  OffsetAvg = Layout::Scale(OffsetAvg);
  if (!positive(vario_avg)) {
    VarioBarAvg[1].y = Layout::Scale(9);
    dy_variobar_av = text_size.cy + 2;
  } else {
    VarioBarAvg[1].y = -Layout::Scale(9);
    clipping_arrow_av[1].y = -clipping_arrow_av[1].y;
    clipping_arrow_av[2].y = -clipping_arrow_av[2].y;
    clipping_arrow_av[3].y = -clipping_arrow_av[3].y;
    clipping_arrow_av_offset = -clipping_arrow_av_offset;
    dy_variobar_av = -1;
  }


  //clip MC Value
  auto mc_val = glide_polar.GetMC();
  if (mc_val > fixed(5))
    mc_val = fixed(5);
  if (!positive(mc_val)) {
    dy_variobar_mc = text_size.cy + 2;
  }else{
    dy_variobar_mc = -1;
  }

  int OffsetMC = int(mc_val / size_divisor);
  OffsetMC = Layout::Scale(OffsetMC);

  for (unsigned i = 0; i < 6; i++) {
    VarioBar[i].y += y0 + dy_variobar;
    VarioBar[i].x = rc.right - Layout::Scale(VarioBar[i].x);
  }

  VarioBar[0].y -= Offset;
  VarioBar[1].y -= Offset;
  VarioBar[2].y -= Offset;

  for (unsigned i = 0; i < 4; i++) {
    VarioBarAvg[i].y += y0 + dy_variobar_av;
    VarioBarAvg[i].x = rc.right-Layout::Scale(VarioBarAvg[i].x);
  }

  VarioBarAvg[0].y -= OffsetAvg;
  VarioBarAvg[1].y -= OffsetAvg;

  // prepare mc arrow
  for (unsigned i = 0; i < 6; i++) {
    mc_arrow[i].y = Layout::Scale(mc_arrow[i].y) + y0
      - OffsetMC + dy_variobar_mc;
    mc_arrow[i].x = rc.right - Layout::Scale(mc_arrow[i].x);
  }

  // prepare clipping arrow
  for (unsigned i = 0; i < 6; i++) {
    clipping_arrow[i].y = Layout::Scale(clipping_arrow[i].y) + y0 - Offset
      + clipping_arrow_offset + dy_variobar;
    clipping_arrow[i].x = rc.right - Layout::Scale(clipping_arrow[i].x);
  }

  // prepare clipping avg
  for (unsigned i = 0; i < 4; i++) {
    clipping_arrow_av[i].y = Layout::Scale(clipping_arrow_av[i].y) + y0 - OffsetAvg
      + clipping_arrow_av_offset + dy_variobar_av;
    clipping_arrow_av[i].x = rc.right-Layout::Scale(clipping_arrow_av[i].x);
  }

  // draw actual vario bar
  if (!positive(vario_gross)) {
    canvas.Select(look.pen_sink);
    canvas.Select(look.brush_sink);
  } else {
    canvas.Select(look.pen_climb);
    canvas.Select(look.brush_climb);
  }

  canvas.DrawPolygon(VarioBar, 6);

  // draw clipping arrow
  if (vario_gross <= fixed(-5) || vario_gross >= fixed(5))
    canvas.DrawPolygon(clipping_arrow, 6);

  // draw avg vario bar
  if (!positive(vario_avg) && vario_bar_avg_enabled) {
      canvas.Select(look.pen_sink);
      canvas.Select(look.brush_sink_avg);
  } else {
    canvas.Select(look.pen_climb);
    canvas.Select(look.brush_climb_avg);
  }

  canvas.DrawPolygon(VarioBarAvg, 4);

  if (vario_avg <= fixed(-5.0) || vario_avg >= fixed(5.0))
      canvas.DrawPolygon(clipping_arrow_av, 4);

  //draw MC arrow
  canvas.Select(look.pen_mc);
  canvas.Select(look.brush_mc);

  canvas.DrawPolygon(mc_arrow, 6);

  //draw text
  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundColor(COLOR_WHITE);

  TextInBoxMode style;
  style.shape = LabelShape::ROUNDED_BLACK;
  style.move_in_view = true;

  if (text_size.cx < Layout::Scale(18)) {
    style.align = TextInBoxMode::Alignment::RIGHT;
    TextInBox(canvas, Value, rc.right, y0, style, rc);
  } else
    TextInBox(canvas, Value, rc.right-Layout::Scale(18), y0, style, rc);
}
Пример #18
0
// This is painting traffic icons on the screen.
void MapWindow::LKDrawFLARMTraffic(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj, const POINT& Orig_Aircraft) {

  if (!EnableFLARMMap) return;

  if (!DrawInfo.FLARM_Available) return;

  // init scaled coords for traffic icon
static int	iCircleSize = 7;
static int	iRectangleSize = 4;
  static short tscaler=0;
  if (DoInit[MDI_DRAWFLARMTRAFFIC]) {

	switch (ScreenSize) {
		case ss480x640:
		case ss480x800:
		case ss800x480:
		case ss640x480:
			iCircleSize = 9;
			iRectangleSize = 5;
			tscaler=NIBLSCALE(7)-2;
			break;
		case ss240x320:
		case ss272x480:
		case ss320x240:
		case ss480x272:
		case ss480x234:
		case ss400x240:
			iCircleSize = 7;
			iRectangleSize = 4;
			tscaler=NIBLSCALE(13)-2;
			break;
		default:
			iCircleSize = 7;
			iRectangleSize = 4;
			tscaler=NIBLSCALE(7);
			break;
	}


	DoInit[MDI_DRAWFLARMTRAFFIC]=false;
  }

  POINT Arrow[5];

  TCHAR lbuffer[50];

  const auto hpold = Surface.SelectObject(LKPen_Black_N1);

  int i;
  int painted=0;

//  double dX, dY;

  TextInBoxMode_t displaymode = {0};
  displaymode.NoSetFont = 1;

  #if 0
  double screenrange = GetApproxScreenRange();
  double scalefact = screenrange/6000.0; // FIX 100820
  #endif




  const auto oldfont = Surface.SelectObject(LK8MapFont);

  for (i=0,painted=0; i<FLARM_MAX_TRAFFIC; i++) {

	// limit to 10 icons map traffic
	if (painted>=10) {
		i=FLARM_MAX_TRAFFIC;
		continue;
	}

	if ( (DrawInfo.FLARM_Traffic[i].ID !=0) && (DrawInfo.FLARM_Traffic[i].Status != LKT_ZOMBIE) ) {

		painted++;

		double target_lon;
		double target_lat;

		target_lon = DrawInfo.FLARM_Traffic[i].Longitude;
		target_lat = DrawInfo.FLARM_Traffic[i].Latitude;

		#if (0) // No scaling, wrong
		if ((EnableFLARMMap==2)&&(scalefact>1.0)) {

			double distance;
			double bearing;

			DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, target_lat, target_lon, &distance, &bearing);
			FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, bearing, distance*scalefact, &target_lat, &target_lon);
		}
		#endif
      
		POINT sc, sc_name, sc_av;
		sc = _Proj.LonLat2Screen(target_lon, target_lat);

		sc_name = sc;

		sc_name.y -= NIBLSCALE(16);
		sc_av = sc_name;

		_tcscpy(lbuffer,_T(""));
		if (DrawInfo.FLARM_Traffic[i].Cn && DrawInfo.FLARM_Traffic[i].Cn[0]!=_T('?')) { // 100322
			_tcscat(lbuffer,DrawInfo.FLARM_Traffic[i].Cn);
		}
		if (DrawInfo.FLARM_Traffic[i].Average30s>=0.1) {
                  size_t len = _tcslen(lbuffer);
                  if (len > 0)
                    _stprintf(lbuffer + len,_T(":%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
                  else
                    _stprintf(lbuffer,_T("%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
		}

		displaymode.Border=1;

		if (_tcslen(lbuffer)>0)
		TextInBox(Surface, &rc, lbuffer, sc.x+tscaler, sc.y+tscaler, &displaymode, false);

		// red circle
		if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) {
			DrawBitmapIn(Surface, sc, hFLARMTraffic,true);
		}
#if 1 // 1
		Arrow[0].x = -4;
		Arrow[0].y = 5;
		Arrow[1].x = 0;
		Arrow[1].y = -6;
		Arrow[2].x = 4;
		Arrow[2].y = 5;
		Arrow[3].x = 0;
		Arrow[3].y = 2;
		Arrow[4].x = -4;
		Arrow[4].y = 5;

		for (int q=0; q < 5; q++)
		{
			Arrow[q].x  = (LONG) ((double)Arrow[q].x * 1.7);
			Arrow[q].y  = (LONG) ((double)Arrow[q].y * 1.7);
		}
#else

		Arrow[0].x = scaler[0];
		Arrow[0].y = scaler[1];
		Arrow[1].x = 0;
		Arrow[1].y = scaler[2];
		Arrow[2].x = scaler[3];
		Arrow[2].y = scaler[1];
		Arrow[3].x = 0;
		Arrow[3].y = scaler[4];
		Arrow[4].x = scaler[0];
		Arrow[4].y = scaler[1];
#endif


/*
		switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				Surface.SelectObject(yellowBrush);
				break;
			case LKT_ZOMBIE:
				Surface.SelectObject(redBrush);
				break;
			default:
				Surface.SelectObject(greenBrush);
				break;
		}
*/
		  /*************************************************************************
		   * calculate climb color
		   *************************************************************************/

		  int iVarioIdx = (int)(2*DrawInfo.FLARM_Traffic[i].Average30s  -0.5)+NO_VARIO_COLORS/2;
		  if(iVarioIdx < 0) iVarioIdx =0;
		  if(iVarioIdx >= NO_VARIO_COLORS) iVarioIdx =NO_VARIO_COLORS-1;
		  Surface.SelectObject(*variobrush[iVarioIdx]);

		  switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				Surface.Rectangle(sc.x-iRectangleSize,  sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize);
				break;
			case LKT_ZOMBIE:
				Surface.DrawCircle(sc.x,  sc.x, iCircleSize, rc, true );
				break;
			default:
				PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle);
				Surface.Polygon(Arrow,5);
				break;
		  }

	}
  }

  Surface.SelectObject(oldfont);
  Surface.SelectObject(hpold);

}
Пример #19
0
//
// Called by LKDrawLook8000, this is what happens when we change mapspace mode, advancing through types.
// We paint infopages, nearest, tri, etc.etc.
// Normally there is plenty of cpu available because the map is not even calculated.
// This is why we bring to the Draw thread, in the nearest pages case, also calculations.
//
void MapWindow::DrawMapSpace(HDC hdc,  RECT rc ) {

  HFONT oldfont;
  HBRUSH hB;

  TextInBoxMode_t TextDisplayMode = {0};
  TCHAR Buffer[LKSIZEBUFFERLARGE*2];
#ifdef DRAWLKSTATUS
  bool dodrawlkstatus=false;
#endif

  static POINT p[10];

  if (MapSpaceMode==MSM_WELCOME) {
	if (INVERTCOLORS)
		hB=LKBrush_Petrol;
	  else
		hB=LKBrush_Mlight;
  } else {
	if (INVERTCOLORS)
	  hB=LKBrush_Mdark;
	else
	  hB=LKBrush_Mlight;

  }
  oldfont = (HFONT)SelectObject(hdc, LKINFOFONT); // save font

  if (MapSpaceMode!=MSM_WELCOME) FillRect(hdc,&rc, hB); 

  if (DoInit[MDI_DRAWMAPSPACE]) {
	p[0].x=0; p[0].y=rc.bottom-BottomSize-NIBLSCALE(2); p[1].x=rc.right-1; p[1].y=p[0].y;
	p[2].x=0; p[2].y=0; p[3].x=rc.right-1; p[3].y=0; // 091230 right-1
	p[4].x=0; p[4].y=0; p[5].x=0; p[5].y=rc.bottom-BottomSize-NIBLSCALE(2);
	p[6].x=rc.right-1; p[6].y=0; p[7].x=rc.right-1; p[7].y=rc.bottom-BottomSize-NIBLSCALE(2); // 091230 right-1

//	p[8].x=0; p[8].y=rc.bottom-BottomSize-NIBLSCALE(2); p[9].x=rc.right; p[9].y=p[8].y;

/*
StartupStore(_T("DOINIT DRAWMAPSPACE 21=%d=%d 22=%d=%d 23=%d=%d 24=%d=%d 31=%d=%d 32=%d=%d\n"),
ConfIP[LKMODE_WP][0],ConfIP21,
ConfIP[LKMODE_WP][1],ConfIP22,
ConfIP[LKMODE_WP][2],ConfIP23,
ConfIP[LKMODE_WP][3],ConfIP24,
ConfIP[LKMODE_NAV][0],ConfIP31,
ConfIP[LKMODE_NAV][1],ConfIP32);
*/

	if (MapSpaceMode==MSM_WELCOME) LoadSplash(hdc,_T("LKPROFILE"));
	DoInit[MDI_DRAWMAPSPACE]=false; 
  }

  // Paint borders in green, but only in nearest pages and welcome
  if (MapSpaceMode==MSM_WELCOME || (!IsMultiMap() && MapSpaceMode!=MSM_MAP) )
  {
	  if (INVERTCOLORS) {
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[2], p[3], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[4], p[5], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[6], p[7], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[0], p[1], RGB_GREEN, rc);
	  } else {
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[2], p[3], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[4], p[5], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[6], p[7], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[0], p[1], RGB_DARKGREEN, rc);
	  }
  }


#ifdef DRAWLKSTATUS 
  if (LKevent==LKEVENT_NEWRUN) dodrawlkstatus=true;
#endif

  // We are entering mapspacemodes with no initial check on configured subpages.
  // Thus we need to ensure that the page is really available, or find the first valid.
  // However, this will prevent direct customkey access to pages!
  // Instead, we do it when we call next page from InfoPageChange
  // if (!ConfIP[ModeIndex][CURTYPE]) NextModeType();
  switch (MapSpaceMode) {
	case MSM_WELCOME:
#if (1)
		if (!DrawInfo.NAVWarning) { 
		static double firsttime=DrawInfo.Time;
		// delayed automatic exit from welcome mode
		if ( DrawInfo.Time > (firsttime+1.0) ) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			if (EnableSoundModes) LKSound(_T("LK_BEEP1.WAV"));
			RefreshMap();
			break;
		}
		}
#endif
		if(GlobalModelType==MODELTYPE_PNA_MINIMAP)
		{
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}

		DrawWelcome8000(hdc, rc);
		break;
	case MSM_MAPTRK:
		SetSideviewPage(IM_HEADING);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPWPT:
		#if 0
		// If there is no destination, force jump to the map
		if (GetOvertargetIndex()<0) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}
		#endif
		SetSideviewPage(IM_NEXT_WP);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPASP:
		SetSideviewPage(IM_NEAR_AS);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPRADAR:
		LKDrawMultimap_Radar(hdc,rc);
		break;
	case MSM_VISUALGLIDE:
		SetSideviewPage(IM_VISUALGLIDE);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPTEST:
		LKDrawMultimap_Test(hdc,rc);
		break;
	case MSM_LANDABLE:
	case MSM_NEARTPS:
	case MSM_AIRPORTS:
		DrawNearest(hdc, rc);
		break;
	case MSM_AIRSPACES:
		DrawAspNearest(hdc, rc);
		break;
	case MSM_COMMON:
	case MSM_RECENT:
		DrawCommon(hdc, rc);
		break;
	case MSM_MAP:
		break;
	case MSM_INFO_THERMAL:
	case MSM_INFO_CRUISE:
	case MSM_INFO_TASK:
	case MSM_INFO_AUX:
	case MSM_INFO_TRI:
	case MSM_INFO_HSI:
	case MSM_INFO_TRF:
	case MSM_INFO_TARGET:
	case MSM_INFO_CONTEST:
		DrawInfoPage(hdc,rc, false);
		break;
	case MSM_TRAFFIC:
		DrawTraffic(hdc,rc);
		break;
	case MSM_THERMALS:
		DrawThermalHistory(hdc,rc);
		break;

  default:
    memset((void*)&TextDisplayMode, 0, sizeof(TextDisplayMode));
    TextDisplayMode.Color = RGB_WHITE;
    TextDisplayMode.NoSetFont = 1; 
    TextDisplayMode.AlligneCenter = 1;
    SelectObject(hdc, LK8TargetFont);
    _stprintf(Buffer,TEXT("MapSpaceMode=%d"),MapSpaceMode);
    TextInBox(hdc, &rc, Buffer, (rc.right-rc.left)/2, NIBLSCALE(50) , 0, &TextDisplayMode, false);
    break;
  }
#ifdef DRAWLKSTATUS
  // no need to clear dodrawlkstatus, it is already reset at each run
  if (dodrawlkstatus) DrawLKStatus(hdc, rc);
#endif
  SelectObject(hdc, oldfont); 
}
Пример #20
0
//
// Called by DrawThread
//
void MapWindow::DrawLKAlarms(HDC hDC, const RECT rc) {

  static unsigned short displaycounter=0;
  static short oldvalidalarm=-1;
  short validalarm=-1;

  // Alarms are working only with a valid GPS fix. No navigator, no alarms.
  if (DrawInfo.NAVWarning) return;

  // give priority to the lowest alarm in list
  if (CheckAlarms(2)) validalarm=2;
  if (CheckAlarms(1)) validalarm=1;
  if (CheckAlarms(0)) validalarm=0;

  // If we have a new alarm, play sound if available and enabled
  if (validalarm>=0) {
	if (EnableSoundModes) {
		switch (validalarm) {
			case 0:
				LKSound(_T("LK_ALARM_ALT1.WAV"));
				break;
			case 1:
				LKSound(_T("LK_ALARM_ALT2.WAV"));
				break;
			case 2:
				LKSound(_T("LK_ALARM_ALT3.WAV"));
				break;
			default:
				break;
		}
	}
	displaycounter=12; // seconds to display alarm on screen, resetting anything set previously
  }

  // Now paint message, even for passed alarms
  if (displaycounter) {

	if (--displaycounter>60) displaycounter=0; // safe check 

	TCHAR textalarm[100];
	short currentalarm=0;
	if (validalarm>=0) {
		currentalarm=validalarm;
		oldvalidalarm=validalarm;
	} else
		if (oldvalidalarm>=0) currentalarm=oldvalidalarm; // safety check

	switch(currentalarm) {
		case 0:
		case 1:
		case 2:
			wsprintf(textalarm,_T("%s %d: %s %d"),
			gettext(_T("_@M1650_")), currentalarm+1, gettext(_T("_@M1651_")),  // ALARM ALTITUDE
			((int)((double)LKalarms[currentalarm].triggervalue*ALTITUDEMODIFY)));
			break;
		default:
			break;
	}

	HFONT oldfont=NULL;
	if (ScreenLandscape)
		oldfont=(HFONT)SelectObject(hDC,LK8TargetFont);
	else
		oldfont=(HFONT)SelectObject(hDC,LK8MediumFont);

	TextInBoxMode_t TextInBoxMode = {0};
	TextInBoxMode.Color = RGB_WHITE;
	TextInBoxMode.NoSetFont=1;
	TextInBoxMode.AlligneCenter = 1;
	TextInBoxMode.WhiteBorder = 1;
	TextInBoxMode.Border = 1;

	// same position for gps warnings: if navwarning, then no alarms. So no overlapping.
        TextInBox(hDC, &rc, textalarm , (rc.right-rc.left)/2, (rc.bottom-rc.top)/3, 0, &TextInBoxMode); 

	SelectObject(hDC,oldfont);
  }

}
Пример #21
0
void
FinalGlideBarRenderer::Draw(Canvas &canvas, const PixelRect &rc,
                            const DerivedInfo &calculated) const
{
  RasterPoint GlideBar[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };
  RasterPoint GlideBar0[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };

  TCHAR Value[10];

  if (!calculated.task_stats.task_valid ||
      !calculated.task_stats.total.solution_remaining.IsOk() ||
      !calculated.task_stats.total.solution_mc0.IsDefined())
    return;

  const int y0 = (rc.bottom + rc.top) / 2;

  // 60 units is size, div by 8 means 60*8 = 480 meters.
  int Offset = ((int)calculated.task_stats.total.solution_remaining.altitude_difference) / 8;
  int Offset0 = ((int)calculated.task_stats.total.solution_mc0.altitude_difference) / 8;
  // TODO feature: should be an angle if in final glide mode

  if (Offset > 60)
    Offset = 60;
  if (Offset < -60)
    Offset = -60;

  Offset = Layout::Scale(Offset);
  if (Offset < 0)
    GlideBar[1].y = Layout::Scale(9);

  if (Offset0 > 60)
    Offset0 = 60;
  if (Offset0 < -60)
    Offset0 = -60;

  Offset0 = Layout::Scale(Offset0);
  if (Offset0 < 0)
    GlideBar0[1].y = Layout::Scale(9);

  for (unsigned i = 0; i < 6; i++) {
    GlideBar[i].y += y0;
    GlideBar[i].x = Layout::Scale(GlideBar[i].x) + rc.left;
  }

  GlideBar[0].y -= Offset;
  GlideBar[1].y -= Offset;
  GlideBar[2].y -= Offset;

  for (unsigned i = 0; i < 6; i++) {
    GlideBar0[i].y += y0;
    GlideBar0[i].x = Layout::Scale(GlideBar0[i].x) + rc.left;
  }

  GlideBar0[0].y -= Offset0;
  GlideBar0[1].y -= Offset0;
  GlideBar0[2].y -= Offset0;

  if ((Offset < 0) && (Offset0 < 0)) {
    // both below
    if (Offset0 != Offset) {
      PixelScalar dy = (GlideBar0[0].y - GlideBar[0].y) +
          (GlideBar0[0].y - GlideBar0[3].y);
      dy = max(Layout::Scale(3), dy);
      GlideBar[3].y = GlideBar0[0].y - dy;
      GlideBar[4].y = GlideBar0[1].y - dy;
      GlideBar[5].y = GlideBar0[2].y - dy;

      GlideBar0[0].y = GlideBar[3].y;
      GlideBar0[1].y = GlideBar[4].y;
      GlideBar0[2].y = GlideBar[5].y;
    } else {
      Offset0 = 0;
    }
  } else if ((Offset > 0) && (Offset0 > 0)) {
    // both above
    GlideBar0[3].y = GlideBar[0].y;
    GlideBar0[4].y = GlideBar[1].y;
    GlideBar0[5].y = GlideBar[2].y;

    if (abs(Offset0 - Offset) < Layout::Scale(4))
      Offset = Offset0;
  }

  // draw actual glide bar
  if (Offset <= 0) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.hpFinalGlideBelowLandable);
      canvas.Select(look.hbFinalGlideBelowLandable);
    } else {
      canvas.Select(look.hpFinalGlideBelow);
      canvas.Select(look.hbFinalGlideBelow);
    }
  } else {
    canvas.Select(look.hpFinalGlideAbove);
    canvas.Select(look.hbFinalGlideAbove);
  }
  canvas.polygon(GlideBar, 6);

  // draw glide bar at mc 0
  if (Offset0 <= 0) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.hpFinalGlideBelowLandable);
      canvas.SelectHollowBrush();
    } else {
      canvas.Select(look.hpFinalGlideBelow);
      canvas.SelectHollowBrush();
    }
  } else {
    canvas.Select(look.hpFinalGlideAbove);
    canvas.SelectHollowBrush();
  }

  if (Offset != Offset0)
    canvas.polygon(GlideBar0, 6);

  // draw cross (x) on final glide bar if unreachable at current Mc
  // or above final glide but impeded by obstacle
  int cross_sign = 0;

  if (!calculated.task_stats.total.IsAchievable())
    cross_sign = 1;
  if (calculated.terrain_warning && (Offset>0))
    cross_sign = -1;

  if (cross_sign != 0) {
    canvas.Select(task_look.bearing_pen);
    canvas.line(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 - 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 + 5));
    canvas.line(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 + 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 - 5));
  }

  Units::FormatUserAltitude(calculated.task_stats.total.solution_remaining.altitude_difference,
                            Value, ARRAY_SIZE(Value),
                            false);

  if (Offset >= 0)
    Offset = GlideBar[2].y + Offset + Layout::Scale(5);
  else if (Offset0 > 0)
    Offset = GlideBar0[1].y - Layout::Scale(15);
  else
    Offset = GlideBar[2].y + Offset - Layout::Scale(15);

  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundColor(COLOR_WHITE);

  TextInBoxMode style;
  style.mode = RM_ROUNDED_BLACK;
  style.bold = true;
  style.move_in_view = true;
  TextInBox(canvas, Value, 0, (int)Offset, style, rc);
}
Пример #22
0
void
FinalGlideBarRenderer::Draw(Canvas &canvas, const PixelRect &rc,
                            const DerivedInfo &calculated,
                            const GlideSettings &glide_settings,
                            const bool final_glide_bar_mc0_enabled) const
{
#ifdef ENABLE_OPENGL
  const ScopeAlphaBlend alpha_blend;
#endif

  BulkPixelPoint GlideBar[6] = {
      { 0, 0 }, { 9, -9 }, { 18, 0 }, { 18, 0 }, { 9, 0 }, { 0, 0 }
  };
  BulkPixelPoint GlideBar0[4] = {
      { 0, 0 }, { 9, -9 }, { 9, 0 }, { 0, 0 }
  };
  BulkPixelPoint clipping_arrow[6] = {
      { 0, 0 }, { 9, 9 }, { 18, 0 }, { 18, 6 }, { 9, 15 }, { 0, 6 }
  };
  BulkPixelPoint clipping_arrow0[4] = {
      { 0, 0 }, { 9, 9 }, { 9, 15 }, { 0, 6 }
  };

  TCHAR Value[10];

  const TaskStats &task_stats = calculated.task_stats;
  const ElementStat &total = task_stats.total;
  const GlideResult &solution = total.solution_remaining;
  const GlideResult &solution_mc0 = total.solution_mc0;

  if (!task_stats.task_valid || !solution.IsOk() || !solution_mc0.IsDefined())
    return;

  const int y0 = (rc.bottom + rc.top) / 2;

  /* NOTE: size_divisor replaces the fixed value 9 that was used throughout
   * the code below which caused fixed size rendering regardless of
   * map size (except the effects of Layout::Scale()). This method
   * is not usable with variable map sizes (e.g. because of the cross-section
   * area). size_divisor is used to introduce a screen size dependent scaling.
   * That workaround is an ugly hack and needs a rework. */
  const int size_divisor =
    std::max(Layout::Scale(3000u / rc.GetHeight()), 4u);

  int dy_glidebar = 0;
  int dy_glidebar0 = 0;

  FormatUserAltitude(solution.SelectAltitudeDifference(glide_settings),
                            Value, false);
  canvas.Select(*look.font);
  const PixelSize text_size = canvas.CalcTextSize(Value);

  int clipping_arrow_offset = Layout::Scale(4);
  int clipping_arrow0_offset = Layout::Scale(4);

  // 468 meters is it's size. Will be divided by 9 to fit screen resolution.
  int altitude_difference = (int)
    solution.SelectAltitudeDifference(glide_settings);
  int altitude_difference0 = (int)
    solution_mc0.SelectAltitudeDifference(glide_settings);
  // TODO feature: should be an angle if in final glide mode

  // cut altitude_difference at +- 468 meters (55 units)
  if (altitude_difference > 468)
    altitude_difference = 468;
  if (altitude_difference < -468)
    altitude_difference = -468;

  // 55 units is size, 468 meters div by 9 means 55.
  int Offset = altitude_difference / size_divisor;
  
  Offset = Layout::Scale(Offset);
  if (altitude_difference <= 0) {
    GlideBar[1].y = Layout::Scale(9);
    dy_glidebar = text_size.cy + 2;
  } else {
    GlideBar[1].y = -Layout::Scale(9);
    clipping_arrow[1].y = -clipping_arrow[1].y;
    clipping_arrow[3].y = -clipping_arrow[3].y;
    clipping_arrow[4].y = -clipping_arrow[4].y;
    clipping_arrow[5].y = -clipping_arrow[5].y;
    clipping_arrow_offset = -clipping_arrow_offset;
    dy_glidebar = -1;
  }

  // cut altitude_difference0 at +- 468 meters (55 units)
  if (altitude_difference0 > 468)
    altitude_difference0 = 468;
  if (altitude_difference0 < -468)
    altitude_difference0 = -468;

  // 55 units is size, therefore div by 9.
  int Offset0 = altitude_difference0 / size_divisor;
  
  Offset0 = Layout::Scale(Offset0);
  if (altitude_difference0 <= 0) {
    GlideBar0[1].y = Layout::Scale(9);
    dy_glidebar0 = text_size.cy + 2;
  } else {
    GlideBar0[1].y = -Layout::Scale(9);
    clipping_arrow0[1].y = -clipping_arrow0[1].y;
    clipping_arrow0[2].y = -clipping_arrow0[2].y;
    clipping_arrow0[3].y = -clipping_arrow0[3].y;
    clipping_arrow0_offset = -clipping_arrow0_offset;
    dy_glidebar0 = -1;
  }

  for (unsigned i = 0; i < 6; i++) {
    GlideBar[i].y += y0 + dy_glidebar;
    GlideBar[i].x = Layout::Scale(GlideBar[i].x) + rc.left;
  }

  GlideBar[0].y -= Offset;
  GlideBar[1].y -= Offset;
  GlideBar[2].y -= Offset;

  for (unsigned i = 0; i < 4; i++) {
    GlideBar0[i].y += y0 + dy_glidebar0;
    GlideBar0[i].x = Layout::Scale(GlideBar0[i].x) + rc.left;
  }

  GlideBar0[0].y -= Offset0;
  GlideBar0[1].y -= Offset0;

  if ((altitude_difference0 >= altitude_difference) && (altitude_difference > 0)) {
    // both above and mc0 arrow larger than mc arrow
    GlideBar0[2].y = GlideBar[1].y;    // both below
    GlideBar0[3].y = GlideBar[0].y;
  }

  // prepare clipping arrow
  for (unsigned i = 0; i < 6; i++) {
    clipping_arrow[i].y = Layout::Scale(clipping_arrow[i].y) + y0 - Offset
      + clipping_arrow_offset + dy_glidebar;
    clipping_arrow[i].x = Layout::Scale(clipping_arrow[i].x) + rc.left;
  }

  // prepare clipping arrow mc0
  for (unsigned i = 0; i < 4; i++) {
    clipping_arrow0[i].y = Layout::Scale(clipping_arrow0[i].y) + y0 - Offset0
      + clipping_arrow0_offset + dy_glidebar0;
    clipping_arrow0[i].x = Layout::Scale(clipping_arrow0[i].x) + rc.left;
  }

  // draw actual glide bar
  if (altitude_difference <= 0) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.pen_below_landable);
      canvas.Select(look.brush_below_landable);
    } else {
      canvas.Select(look.pen_below);
      canvas.Select(look.brush_below);
    }
  } else {
    canvas.Select(look.pen_above);
    canvas.Select(look.brush_above);
  }
  canvas.DrawPolygon(GlideBar, 6);

  // draw clipping arrow
  if ((altitude_difference <= -468 ) || (altitude_difference >= 468))
    canvas.DrawPolygon(clipping_arrow, 6);

  // draw glide bar at mc 0
  if (altitude_difference0 <= 0 && final_glide_bar_mc0_enabled) {
    if (calculated.common_stats.landable_reachable) {
      canvas.Select(look.pen_below_landable);
      canvas.Select(look.brush_below_landable_mc0);
    } else {
      canvas.Select(look.pen_below);
      canvas.Select(look.brush_below_mc0);
    }
  } else {
    canvas.Select(look.pen_above);
    canvas.Select(look.brush_above_mc0);
  }

  if ( ( (altitude_difference != altitude_difference0) || (altitude_difference0 < 0) )
      && final_glide_bar_mc0_enabled) {
    canvas.DrawPolygon(GlideBar0, 4);

    if ((altitude_difference0 <= -468 ) || (altitude_difference0 >= 468))
      canvas.DrawPolygon(clipping_arrow0, 4);
  }

  // draw cross (x) on final glide bar if unreachable at current Mc
  // or above final glide but impeded by obstacle
  int cross_sign = 0;

  if (!total.IsAchievable())
    cross_sign = 1;
  if (calculated.terrain_warning_location.IsValid() &&
      altitude_difference > 0 )
    cross_sign = -1;

  if (cross_sign != 0) {
    canvas.Select(task_look.bearing_pen);
    canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 - 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 + 5));
    canvas.DrawLine(Layout::Scale(9 - 5), y0 + cross_sign * Layout::Scale(9 + 5),
                Layout::Scale(9 + 5), y0 + cross_sign * Layout::Scale(9 - 5));
  }

  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundColor(COLOR_WHITE);

  TextInBoxMode style;
  style.shape = LabelShape::ROUNDED_BLACK;
  style.move_in_view = true;

  if (text_size.cx < Layout::Scale(18)) {
    style.align = TextInBoxMode::Alignment::RIGHT;
    TextInBox(canvas, Value, Layout::Scale(18), y0, style, rc);
  } else
    TextInBox(canvas, Value, 0, y0, style, rc);

}
Пример #23
0
void MapWindow::DrawWaypointsNew(HDC hdc, const RECT rc)
{
  unsigned int i; 
  int bestwp=-1;
  TCHAR Buffer[LKSIZEBUFFER];
  TCHAR Buffer2[LKSIZEBUFFER];
  TCHAR sAltUnit[LKSIZEBUFFERUNIT];
  TextInBoxMode_t TextDisplayMode = {0};

  static int resizer[10]={ 20,20,20,3,5,8,10,12,0 };


  // if pan mode, show full names
  int pDisplayTextType = DisplayTextType;

  if (!WayPointList) return;

  _tcscpy(sAltUnit, Units::GetAltitudeName());

  MapWaypointLabelListCount = 0;

  int arrivalcutoff=0, foundairport=0;
  bool isairport;
  bool islandpoint;

  // setting decluttericons will not paint outlanding, and use minrunway to declutter even more
  bool decluttericons=false;
  // inrange : max scale allowed to print non-landable waypoints 
  bool inrange=true; 
  // minimal size of a runway to paint it while decluttering
  int minrunway=0;

  //
  // RealScale
  //
  //   2km 	 1.42
  // 3.5km	 2.5
  //   5km	 3.57
  // 7.5km	 5.35
  //  10km	 7.14
  //  15km	10.71
  //  20km	14.28
  //  25km	17.85
  //  40km	28.57
  //  50km	35.71
  //  75km	53.57

  switch(DeclutterMode) {
	case dmDisabled:
		//inrange=(MapWindow::zoom.RealScale() <=18 ? true:false); // 17.85, 25km scale
		inrange=(MapWindow::zoom.RealScale() <=15 ? true:false); // 14.28, 20km scale
		decluttericons=false;
		break;
	case dmLow:
		inrange=(MapWindow::zoom.RealScale() <=11 ? true:false); // 10.71, 15km scale
		decluttericons=(MapWindow::zoom.RealScale() >=14 ? true : false);
		minrunway=200;
		break;
	case dmMedium:
		inrange=(MapWindow::zoom.RealScale() <=10 ? true:false);
		decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false);
		minrunway=400;
		break;
	case dmHigh:
		inrange=(MapWindow::zoom.RealScale() <=10 ? true:false);
		decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false);
		minrunway=800;
		break;
	case dmVeryHigh:
		inrange=(MapWindow::zoom.RealScale() <=10 ? true:false);
		decluttericons=(MapWindow::zoom.RealScale() >=10 ? true : false);
		minrunway=1600;
		break;
	default:
		LKASSERT(0);
		break;
  }

  if (MapWindow::zoom.RealScale() <=20) for(i=0;i<NumberOfWayPoints;i++) {

	if (WayPointList[i].Visible != TRUE )	continue; // false may not be FALSE?

	if (WayPointCalc[i].IsAirport) {
		if (WayPointList[i].Reachable == FALSE)	{ 
			SelectObject(hDCTemp,hBmpAirportUnReachable);
		} else {
			SelectObject(hDCTemp,hBmpAirportReachable);
			if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) {
				arrivalcutoff = (int)(WayPointList[i].AltArivalAGL);
				bestwp=i; foundairport++;
			}
		}
	} else {
		if ( WayPointCalc[i].IsOutlanding ) {
			// outlanding
			if (WayPointList[i].Reachable == FALSE)
				SelectObject(hDCTemp,hBmpFieldUnReachable);
			else { 
				SelectObject(hDCTemp,hBmpFieldReachable);
				// get the outlanding as bestwp only if no other choice
				if (foundairport == 0) { 
					// do not set arrivalcutoff: any next reachable airport is better than an outlanding
					if ( arrivalcutoff < (int)(WayPointList[i].AltArivalAGL)) bestwp=i;  
				}
			}
		} else continue; // do not draw icons for normal turnpoints here
	}

    if(Appearance.IndLandable == wpLandableDefault) 
    {
      double fScaleFact =MapWindow::zoom.RealScale();
      if(fScaleFact < 0.1)  fScaleFact = 0.1; // prevent division by zero

      fScaleFact = zoom.DrawScale();
      if(fScaleFact > 20000.0) fScaleFact = 20000.0; // limit to prevent huge airfiel symbols
      if(fScaleFact < 1600)   fScaleFact = 1600; // limit to prevent tiny airfiel symbols

	if (decluttericons) {
		if (WayPointCalc[i].IsAirport && (WayPointList[i].RunwayLen>minrunway || WayPointList[i].RunwayLen==0)) {
  	  		DrawRunway(hdc,&WayPointList[i],rc, fScaleFact);
		}

	} else
  	  DrawRunway(hdc,&WayPointList[i],rc, fScaleFact);
    }
    else
    {
	  DrawBitmapX(hdc, WayPointList[i].Screen.x-10, WayPointList[i].Screen.y-10, 20,20, hDCTemp,0,0,SRCPAINT,false);
  	  DrawBitmapX(hdc, WayPointList[i].Screen.x-10, WayPointList[i].Screen.y-10, 20,20, hDCTemp,20,0,SRCAND,false);
    }

  } // for all waypoints

  if (foundairport==0 && bestwp>=0)  arrivalcutoff = (int)WayPointList[bestwp].AltArivalAGL;


  for(i=0;i<NumberOfWayPoints;i++)
    {
      if(WayPointList[i].Visible )
	{

	    bool irange = false;
	    bool intask = false;
	    bool islandable;	// isairport+islandpoint
	    bool excluded=false;
	    bool dowrite;

	    intask = WaypointInTask(i);
	    dowrite = intask; // initially set only for intask
	    memset((void*)&TextDisplayMode, 0, sizeof(TextDisplayMode));

	    // airports are also landpoints. should be better handled
	    isairport=((WayPointList[i].Flags & AIRPORT) == AIRPORT);
	    islandpoint=((WayPointList[i].Flags & LANDPOINT) == LANDPOINT);

	islandable=WayPointCalc[i].IsLandable;

 	    // always in range if MapScale <=10 
	    irange = inrange;

	    if(MapWindow::zoom.RealScale() > 20) { 
	      SelectObject(hDCTemp,hInvSmall);
	      irange=false;
	      goto NiklausWirth; // with compliments
	    } 
	    if (decluttericons) {
		if (! (WayPointCalc[i].IsAirport && (WayPointList[i].RunwayLen>minrunway || WayPointList[i].RunwayLen==0))) {
		      SelectObject(hDCTemp,hInvSmall);
		      irange=false;
		      goto NiklausWirth;
		}
            }

	    if( islandable ) { 

	      if(WayPointList[i].Reachable){

		TextDisplayMode.Reachable = 1;

		if ( isairport )
		  SelectObject(hDCTemp,hBmpAirportReachable);
		else
		  SelectObject(hDCTemp,hBmpFieldReachable);

		if ((GetMultimap_Labels()<MAPLABELS_ALLOFF)||intask) { 

		  dowrite = true;
		  // exclude outlandings worst than visible airports, only when there are visible reachable airports!
		  if ( isairport==false && islandpoint==true ) {
		    if ( (int)WayPointList[i].AltArivalAGL >=2000 ) { // more filter
		      excluded=true;
		    } else {
		      if ( (bestwp>=0) && (i==(unsigned)bestwp) && (foundairport==0) ) { // this outlanding is the best option
			isairport=true;
			islandpoint=false; // make it an airport TODO paint it as best
		      } else
			{
			  if ( foundairport >0 ) {
			    if ( (int)WayPointList[i].AltArivalAGL <= arrivalcutoff ) {
			      excluded=true;
			    } 
			  }
			}
		    }

		  }  else
		    // do not display airport arrival if close to the best so far.
		    // ex: best arrival is 1200m, include onlye below 1200/4  (prevent division by zero)
		    // This way we only display far points, and skip closer points 
		    // WE NEED MORE INFO ABOUT LANDING POINTS: THE .CUP FORMAT WILL LET US KNOW WHAT IS
		    // BEST TO SHOW AND WHAT IS NOT. Winpilot format is useless here.
		    {
		      dowrite=true;// TEST FIX not necessary probably
		      // it's an airport
		      if ( (bestwp>=0) && (i != (unsigned)bestwp) && (arrivalcutoff>600) ) {
			if ( (arrivalcutoff / ((int)WayPointList[i].AltArivalAGL+1))<4 ) {
			  excluded=true;
			}
		      }
		    } 
		}


	      } else  // landable waypoint is unreachable
		{
		  dowrite=true; 
		  if ( isairport ) {
		    SelectObject(hDCTemp,hBmpAirportUnReachable);
		  } else {
		    SelectObject(hDCTemp,hBmpFieldUnReachable);
		  }
		}
	    } else { // waypoint is an ordinary turnpoint
	      if(MapWindow::zoom.RealScale() > 4) {
		if (BlackScreen) 
			SelectObject(hDCTemp,hInvSmall);
		else
			SelectObject(hDCTemp,hSmall);
	      } else {
		if (BlackScreen) 
			SelectObject(hDCTemp,hInvTurnPoint);
		else
			SelectObject(hDCTemp,hTurnPoint);
	      }

	    } // end landable-not landable

	  NiklausWirth:

	    if (intask || (OutlinedTp==(OutlinedTp_t)otAll) ) { 
	      TextDisplayMode.WhiteBold = 1;
	      TextDisplayMode.Color=RGB_WHITE; 
	    }
	

	// No matter of how we thought to draw it, let it up to the user..
	switch(NewMapDeclutter) {
		case 0:
			excluded=false; // no decluttering: show all airports and outlandings
			break;
		case 1:
			if ( isairport ) excluded=false; //  show all airports, declutter outlandings
			break;
		default:
			break; // else work normally
	}


	    // here come both turnpoints and landables..
	    if( intask || irange || dowrite) {  // irange always set when MapScale <=10 

	      bool draw_alt = TextDisplayMode.Reachable && ((GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask); // 100711 reachable landing point!

	      if (excluded==true) draw_alt=false; // exclude close outlandings

	      switch(pDisplayTextType) {

	     case DISPLAYNAME:
	     case DISPLAYFIRSTTHREE:
	     case DISPLAYFIRSTFIVE:
	     case DISPLAYFIRST8:
	     case DISPLAYFIRST10:
	     case DISPLAYFIRST12:

		dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable;  // 100711
		if ( (islandable && !isairport) && MapWindow::zoom.RealScale() >=10 ) dowrite=0; // FIX then no need to go further

		// 101215 
		if (DisplayTextType == DISPLAYNAME) {
			_tcscpy(Buffer2,WayPointList[i].Name);
		} else {
			LK_tcsncpy(Buffer2, WayPointList[i].Name, resizer[DisplayTextType]);
		}
		// ConvToUpper(Buffer2); 

		if (draw_alt) {
		  if ( ArrivalValue == (ArrivalValue_t) avAltitude ) {
			if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) )
		  		wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY));
			else
		  		wsprintf(Buffer, TEXT("%s:%d%s"), Buffer2, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit);
		  } else 
			wsprintf(Buffer, TEXT("%s:%d"), Buffer2, (int)WayPointCalc[i].GR);


		  if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
			  TextDisplayMode.Border = 1;
			  TextDisplayMode.WhiteBold = 0;
		  } else
		  	TextDisplayMode.WhiteBold = 1; // outlined 
		  	TextDisplayMode.Color=RGB_WHITE; 
		} else {
			//wsprintf(Buffer, TEXT("%s"),Buffer2);
			_tcscpy(Buffer,Buffer2);
			if (islandable && isairport) {
				TextDisplayMode.WhiteBold = 1; // outlined 
				TextDisplayMode.Color=RGB_WHITE; 
			}
		}
				  
		break;
	      case DISPLAYNUMBER:
		dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable; 
		if ( (islandable && !isairport) && MapWindow::zoom.RealScale() >=10 ) dowrite=0; // FIX then no need to go further

		if (draw_alt) {
		  if ( ArrivalValue == (ArrivalValue_t) avAltitude ) {
			if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) )
		  		wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY));
			else
		  		wsprintf(Buffer, TEXT("%d:%d%s"), WayPointList[i].Number, (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), sAltUnit);
		  } else
		  	wsprintf(Buffer, TEXT("%d:%d"), WayPointList[i].Number, (int)(WayPointCalc[i].GR));
		  if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
			  TextDisplayMode.Border = 1;
			  TextDisplayMode.WhiteBold = 0;
		  } else
		  	TextDisplayMode.WhiteBold = 1; // outlined 
	      		TextDisplayMode.Color=RGB_WHITE; 
		} else {
		  wsprintf(Buffer, TEXT("%d"),WayPointList[i].Number);
		  if (islandable && isairport) {
		    TextDisplayMode.WhiteBold = 1; // outlined 
	      		TextDisplayMode.Color=RGB_WHITE; 
		  }
		}
		break;
				  
				  

	      case DISPLAYNAMEIFINTASK: 
		dowrite = intask;
		if (intask) {
		  if (draw_alt) {
		  if ( ArrivalValue == (ArrivalValue_t) avAltitude ) {
			if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) )
			    wsprintf(Buffer, TEXT("%s:%d"),
				     WayPointList[i].Name, 
				     (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY));
			else
			    wsprintf(Buffer, TEXT("%s:%d%s"),
				     WayPointList[i].Name, 
				     (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), 
				     sAltUnit);


		  } else
			    wsprintf(Buffer, TEXT("%s:%d"),
				     WayPointList[i].Name, 
				     (int)(WayPointCalc[i].GR)); 

		  if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
			  TextDisplayMode.Border = 1;
			  TextDisplayMode.WhiteBold = 0;
		  } else
		  	TextDisplayMode.WhiteBold = 1; // outlined 
	      		TextDisplayMode.Color=RGB_WHITE; 

		  }
		  else {
		    wsprintf(Buffer, TEXT("%s"),WayPointList[i].Name);
		    // TODO CHECK THIS, UNTESTED..
                    if (islandable && isairport) {
		       TextDisplayMode.WhiteBold = 1; // outlined 
	      		TextDisplayMode.Color=RGB_WHITE; 
		    }
		  }
		}
			else {
		  		wsprintf(Buffer, TEXT(" "));
				dowrite=true;
			}
		break;
	      case DISPLAYNONE:
		dowrite = (GetMultimap_Labels()<MAPLABELS_ONLYTOPO) || intask || islandable; 
		if (draw_alt) {
		  if ( ArrivalValue == (ArrivalValue_t) avAltitude ) {
			if ( (MapBox == (MapBox_t)mbUnboxedNoUnit) || (MapBox == (MapBox_t)mbBoxedNoUnit) )
			  wsprintf(Buffer, TEXT("%d"), 
				   (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY));
			else
			  wsprintf(Buffer, TEXT("%d%s"), 
				   (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY), 
				   sAltUnit);
		  } else
			  wsprintf(Buffer, TEXT("%d"), 
				   (int)(WayPointCalc[i].GR) );

		  if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
			  TextDisplayMode.Border = 1;
			  TextDisplayMode.WhiteBold = 0;
		  } else
		  	TextDisplayMode.WhiteBold = 1; // outlined 
	      	    TextDisplayMode.Color=RGB_WHITE; 
		}
		else {
		  	wsprintf(Buffer, TEXT(" "));
		}
		break;

	      default:
#if (WINDOWSPC<1)
		//ASSERT(0);
#endif
		break;

	      } // end intask/irange/dowrite

    if (MapWindow::zoom.RealScale()<20 && islandable && dowrite) {
      TextInBox(hdc, &rc, Buffer, WayPointList[i].Screen.x+5, WayPointList[i].Screen.y, 0, &TextDisplayMode, true); 
      dowrite=false; // do not pass it along
    }

		// Do not show takeoff for gliders, check TakeOffWayPoint 
		if (i==RESWP_TAKEOFF) {
			if (TakeOffWayPoint) {
				intask=false; // 091031 let TAKEOFF be decluttered
				WayPointList[i].Visible=TRUE;
			} else {
				WayPointList[i].Visible=FALSE;
				dowrite=false;
			}
		}

		if(i==RESWP_OPTIMIZED) {
			dowrite = DoOptimizeRoute();
		}


	      if (dowrite) { 
          MapWaypointLabelAdd(
                  Buffer,
                  WayPointList[i].Screen.x+5,
                  WayPointList[i].Screen.y,
                  &TextDisplayMode,
                  (int)(WayPointList[i].AltArivalAGL*ALTITUDEMODIFY),
                  intask,islandable,isairport,excluded,i,WayPointList[i].Style);
	      }
	    } // end if intask
      
	     { ; }
	} // if visible
    } // for all waypoints
 
  qsort(&MapWaypointLabelList, MapWaypointLabelListCount, sizeof(MapWaypointLabel_t), MapWaypointLabelListCompare);

  int j;

  // now draw task/landable waypoints in order of range (closest last)
  // writing unconditionally

  for (j=MapWaypointLabelListCount-1; j>=0; j--){

    MapWaypointLabel_t *E = &MapWaypointLabelList[j];

    // draws if they are in task unconditionally,
    // otherwise, does comparison
    if ( E->inTask || (E->isLandable && !E->isExcluded) ) { 

	TextInBox(hdc, &rc, E->Name, E->Pos.x, E->Pos.y, 0, &(E->Mode), false); 

	// At low zoom, dont print the bitmap because drawn task would make it look offsetted
	if(MapWindow::zoom.RealScale() > 2) continue;

    // If we are at low zoom, use a dot for icons, so we dont clutter the screen
    if(MapWindow::zoom.RealScale() > 1) {
	if (BlackScreen) 
 		 SelectObject(hDCTemp,hInvSmall);
	else
 		 SelectObject(hDCTemp,hSmall);
    } else {
	if (BlackScreen)
		SelectObject(hDCTemp,hInvTurnPoint);
	else
		SelectObject(hDCTemp,hTurnPoint);
    }
    DrawBitmapX(hdc,
	    E->Pos.x-10,
	    E->Pos.y-10,
	    20,20,
	    hDCTemp,0,0,SRCPAINT,false);
        
    DrawBitmapX(hdc,
	    E->Pos.x-10,
	    E->Pos.y-10,
	    20,20,
	    hDCTemp,20,0,SRCAND,false);

    } // wp in task
  } // for all waypoint, searching for those in task

  // now draw normal waypoints in order of range (furthest away last)
  // without writing over each other (or the task ones)
  for (j=0; j<MapWaypointLabelListCount; j++) {

    MapWaypointLabel_t *E = &MapWaypointLabelList[j];

    if (!E->inTask && !E->isLandable ) {
      if ( TextInBox(hdc, &rc, E->Name, E->Pos.x, E->Pos.y, 0, &(E->Mode), true) == true) {

	// If we are at low zoom, use a dot for icons, so we dont clutter the screen
	if(MapWindow::zoom.RealScale() > 4) {
		if (BlackScreen) 
	 		 SelectObject(hDCTemp,hInvSmall);
		else
	 		 SelectObject(hDCTemp,hSmall);
	} else {
		// We switch all styles in the correct order, to force a jump table by the compiler
		// It would be much better to use an array of bitmaps, but no time to do it for 3.0
		switch(E->style) {
			case STYLE_NORMAL:
				goto turnpoint;
				break;

			// These are not used here in fact
			case STYLE_AIRFIELDGRASS:
			case STYLE_OUTLANDING:
			case STYLE_GLIDERSITE:
			case STYLE_AIRFIELDSOLID:
				goto turnpoint;
				break;

			case STYLE_MTPASS:
				SelectObject(hDCTemp,hMountpass);
				break;

			case STYLE_MTTOP:
				SelectObject(hDCTemp,hMountop);
				break;

			case STYLE_SENDER:
				SelectObject(hDCTemp,hSender);
				break;

			case STYLE_VOR:
				goto turnpoint;
				break;

			case STYLE_NDB:
				SelectObject(hDCTemp,hNdb);
				break;

			case STYLE_COOLTOWER:
				goto turnpoint;
				break;

			case STYLE_DAM:
				SelectObject(hDCTemp,hDam);
				break;

			case STYLE_TUNNEL:
				goto turnpoint;
				break;

			case STYLE_BRIDGE:
				SelectObject(hDCTemp,hBridge);
				break;

			case STYLE_POWERPLANT:
			case STYLE_CASTLE:
				goto turnpoint;
				break;

			case STYLE_INTERSECTION:
				SelectObject(hDCTemp,hIntersect);
				break;

			case STYLE_TRAFFIC:
				goto turnpoint;
				break;
			case STYLE_THERMAL:
				SelectObject(hDCTemp,hLKThermal);
				break;

			case STYLE_MARKER:
				SelectObject(hDCTemp,hBmpMarker);
				break;

			default:
turnpoint:
				if (BlackScreen)
					SelectObject(hDCTemp,hInvTurnPoint);
				else
					SelectObject(hDCTemp,hTurnPoint);
				break;

		} // switch estyle
	} // below zoom threshold

	// We dont do stretching here. We are using different bitmaps for hi res.
	// The 20x20 size is large enough to make much bigger icons than the old ones.
	DrawBitmapX(hdc,
		    E->Pos.x-10,
		    E->Pos.y-10,
		    20,20,
		    hDCTemp,0,0,SRCPAINT,false);
        
	DrawBitmapX(hdc,
		    E->Pos.x-10,
		    E->Pos.y-10,
		    20,20,
		    hDCTemp,20,0,SRCAND,false);
      }
    }
  }

} // end DrawWaypoint
Пример #24
0
void
GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc,
                            const MapWindowProjection &projection) const
{
  if (!projection.IsValid())
    return;

  StaticString<80> buffer;

  fixed map_width = projection.GetScreenWidthMeters();

  const Font &font = *look.overlay_font;
  canvas.Select(font);
  FormatUserMapScale(map_width, buffer.buffer(), true);
  PixelSize text_size = canvas.CalcTextSize(buffer);

  const PixelScalar text_padding_x = Layout::GetTextPadding();
  const PixelScalar height = font.GetCapitalHeight()
    + Layout::GetTextPadding();

  PixelScalar x = 0;
  look.map_scale_left_icon.Draw(canvas, 0, rc.bottom - height);

  x += look.map_scale_left_icon.GetSize().cx;
  canvas.DrawFilledRectangle(x, rc.bottom - height,
                             x + 2 * text_padding_x + text_size.cx,
                             rc.bottom, COLOR_WHITE);

  canvas.SetBackgroundTransparent();
  canvas.SetTextColor(COLOR_BLACK);
  x += text_padding_x;
  canvas.DrawText(x,
                  rc.bottom - font.GetAscentHeight() - Layout::Scale(1),
                  buffer);

  x += text_padding_x + text_size.cx;
  look.map_scale_right_icon.Draw(canvas, x, rc.bottom - height);

  buffer.clear();
  if (GetMapSettings().auto_zoom_enabled)
    buffer = _T("AUTO ");

  switch (follow_mode) {
  case FOLLOW_SELF:
    break;

  case FOLLOW_PAN:
    buffer += _T("PAN ");
    break;
  }

  const UIState &ui_state = GetUIState();
  if (ui_state.auxiliary_enabled) {
    buffer += ui_state.panel_name;
    buffer += _T(" ");
  }

  if (Basic().gps.replay)
    buffer += _T("REPLAY ");
  else if (Basic().gps.simulator) {
    buffer += _("Simulator");
    buffer += _T(" ");
  }

  if (GetComputerSettings().polar.ballast_timer_active)
    buffer.AppendFormat(
        _T("BALLAST %d LITERS "),
        (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres());

  if (weather != nullptr && weather->GetParameter() > 0) {
    const TCHAR *label = weather->ItemLabel(weather->GetParameter());
    if (label != nullptr)
      buffer += label;
  }

  if (!buffer.empty()) {
    int y = rc.bottom - height;

    TextInBoxMode mode;
    mode.vertical_position = TextInBoxMode::VerticalPosition::ABOVE;
    mode.shape = LabelShape::OUTLINED;

    TextInBox(canvas, buffer, 0, y, mode, rc, nullptr);
  }
}
Пример #25
0
void MapWindow::DrawGlideThroughTerrain(LKSurface& Surface, const RECT& rc) {
  LKPen hpOld;

  //double h,dh;
  TCHAR hbuf[10];
  static bool doinit=true;
  static TextInBoxMode_t tmode = {0};
  bool wrotevalue=false;

  if (doinit) {
    memset((void*)&tmode, 0, sizeof(TextInBoxMode_t));
    tmode.Border=1;
    doinit=false;
  }

  #ifdef GTL2
  bool ValidTP = ValidTaskPoint(ActiveWayPoint);

  // draw glide terrain line around next WP
  bool DrawGTL2 = ValidTP && (FinalGlideTerrain > 2);
  static bool LastDrewGTL2 = false;

  if (DrawGTL2) {
    int wp_index = (DoOptimizeRoute() || ACTIVE_WP_IS_AAT_AREA) ? 
                   RESWP_OPTIMIZED : TASKINDEX;

    double alt_arriv = WayPointCalc[wp_index].AltArriv[AltArrivMode];
    
    // Calculate arrival altitude at the next waypoint relative to
    // the "terrain height" safety setting.

    if (CheckSafetyAltitudeApplies(wp_index))
      alt_arriv += SAFETYALTITUDEARRIVAL/10; // AGL
    alt_arriv -= SAFETYALTITUDETERRAIN/10;   // rel. to "terrain height"

    if (alt_arriv <= 0) DrawGTL2 = false;
  }
  
  if (LastDrewGTL2 != DrawGTL2) {
    LastDrewGTL2 = DrawGTL2;
    if (!DrawGTL2) ClearGTL2(); // clear next-WP glide terrain line
  }
  #endif

  hpOld = Surface.SelectObject(hpTerrainLineBg); 

  #ifdef GTL2
  // Draw the wide, solid part of the glide terrain line.
  #else
  // draw a dashed perimetral line first
  #endif
  Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc);

  // draw perimeter if selected and during a flight
  #ifdef GTL2
  if (((FinalGlideTerrain == 1) || (FinalGlideTerrain == 3)) || 
     ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && FinalGlideTerrain)) { 
  #else
  if ((FinalGlideTerrain==1) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && (FinalGlideTerrain==2))) { 
  #endif
	Surface.SelectObject(hpTerrainLine);
	Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc);
  }
  
  #ifdef GTL2  
  // draw glide terrain line around next waypoint
  if (DrawGTL2) {
    // Draw a solid white line.
    Surface.SelectObject(LKPen_White_N2);
    Surface.Polyline(Groundline2, NUMTERRAINSWEEPS+1, rc);

    // Draw a dashed red line.
    Surface.DrawDashPoly(NIBLSCALE(2), RGB_RED, Groundline2, NUMTERRAINSWEEPS+1, rc);
  }
  #endif

  // draw red cross obstacles only if destination looks reachable!
  // only if using OVT_TASK of course!

  #ifdef GTL2
  if ((OvertargetMode == OVT_TASK) && DerivedDrawInfo.Flying && ValidTP)
  #else
  if ( (OvertargetMode==OVT_TASK) && DerivedDrawInfo.Flying && ValidTaskPoint(ActiveWayPoint))
  #endif
  if (WayPointCalc[TASKINDEX].AltArriv[AltArrivMode] >0) { 

	POINT sc;
	// If calculations detected an obstacle...
	if ((DerivedDrawInfo.TerrainWarningLatitude != 0.0) &&(DerivedDrawInfo.TerrainWarningLongitude != 0.0)) {

		// only if valid position, and visible
		if (DerivedDrawInfo.FarObstacle_Lon >0) 
		if (PointVisible(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat)) {
			LatLon2Screen(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat, sc);
			DrawBitmapIn(Surface, sc, hTerrainWarning,true);

			if (DerivedDrawInfo.FarObstacle_AltArriv <=-50 ||  DerivedDrawInfo.FarObstacle_Dist<5000 ) {
				_stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.FarObstacle_AltArriv);
				TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); 
				wrotevalue=true;
			}
		} // visible far obstacle

		if (PointVisible(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude)) {
			LatLon2Screen(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude, sc);
			DrawBitmapIn(Surface, sc, hTerrainWarning,true);
#if 0
			// 091203 add obstacle altitude on moving map
			h =  max(0,RasterTerrain::GetTerrainHeight(DerivedDrawInfo.TerrainWarningLatitude, 
				DerivedDrawInfo.TerrainWarningLongitude)); 
			if (h==TERRAIN_INVALID) h=0; //@ 101027 FIX but unused
			dh = CALCULATED_INFO.NavAltitude - h - (SAFETYALTITUDETERRAIN/10);
			_stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*dh);
			TextInBox(hDC,&rc,hbuf,sc.x+NIBLSCALE(10), sc.y, 0, tmode,false); 
#else
			// if far obstacle was painted with value...
			if (wrotevalue) {
				// if it is not too near the nearest..
				if ( (fabs(DerivedDrawInfo.FarObstacle_Lon - DerivedDrawInfo.TerrainWarningLongitude) >0.02) &&
					(fabs(DerivedDrawInfo.FarObstacle_Lat - DerivedDrawInfo.TerrainWarningLatitude) >0.02)) {
					// and it the arrival altitude is actually negative (rounding terrain errors?)
					if ( DerivedDrawInfo.ObstacleAltArriv <=-50)
					// and there is a significant difference in the numbers, then paint value also for nearest
					if (  fabs(DerivedDrawInfo.ObstacleAltArriv - DerivedDrawInfo.FarObstacle_AltArriv) >100 ) {
						_stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv);
						TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); 
					}
				}
			} else {
				// else paint value only if meaningful or very close to us
				// -1 to 10m become -1 for rounding errors
				if ( (DerivedDrawInfo.ObstacleAltArriv >-1) && (DerivedDrawInfo.ObstacleAltArriv <10))
					DerivedDrawInfo.ObstacleAltArriv=-1;
				if (DerivedDrawInfo.ObstacleAltArriv <=-50 ||  
				 ((DerivedDrawInfo.ObstacleAltArriv<0) && (DerivedDrawInfo.ObstacleDistance<5000)) ) {

					_stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv);
					TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); 
				}
			}
#endif
		} // visible nearest obstacle
	} // obstacles detected
  } // within glide range

  Surface.SelectObject(hpOld);
}
Пример #26
0
// This is painting traffic icons on the screen.
void MapWindow::LKDrawFLARMTraffic(HDC hDC, RECT rc, POINT Orig_Aircraft) {

  if (!EnableFLARMMap) return;

  if (!DrawInfo.FLARM_Available) return;

  // init scaled coords for traffic icon
static int	iCircleSize = 7;
static int	iRectangleSize = 4;
  static short scaler[5];
  static short tscaler=0;
  if (DoInit[MDI_DRAWFLARMTRAFFIC]) {

	switch (ScreenSize) {
		case ss480x640:
		case ss480x800:
		case ss896x672:
		case ss800x480:
		case ss640x480:
			iCircleSize = 9;
			iRectangleSize = 5;
			scaler[0]=-1*(NIBLSCALE(4)-2);
			scaler[1]=NIBLSCALE(5)-2;
			scaler[2]=-1*(NIBLSCALE(6)-2);
			scaler[3]=NIBLSCALE(4)-2;
			scaler[4]=NIBLSCALE(2)-2;
			tscaler=NIBLSCALE(7)-2;
			break;
		case ss240x320:
		case ss272x480:
		case ss320x240:
		case ss480x272:
		case ss720x408:
		case ss480x234:
		case ss400x240:
			iCircleSize = 7;
			iRectangleSize = 4;
			scaler[0]=-1*(NIBLSCALE(8)-2);
			scaler[1]=NIBLSCALE(10)-2;
			scaler[2]=-1*(NIBLSCALE(12)-2);
			scaler[3]=NIBLSCALE(8)-2;
			scaler[4]=NIBLSCALE(4)-2;
			tscaler=NIBLSCALE(13)-2;
			break;
		default:
			iCircleSize = 7;
			iRectangleSize = 4;
			scaler[0]=-1*NIBLSCALE(4);
			scaler[1]=NIBLSCALE(5);
			scaler[2]=-1*NIBLSCALE(6);
			scaler[3]=NIBLSCALE(4);
			scaler[4]=NIBLSCALE(2);
			tscaler=NIBLSCALE(7);
			break;
	}


	DoInit[MDI_DRAWFLARMTRAFFIC]=false;
  }

  HPEN hpold;
  HPEN thinBlackPen = LKPen_Black_N1;
  POINT Arrow[5];

  TCHAR lbuffer[50];

  hpold = (HPEN)SelectObject(hDC, thinBlackPen);

  int i;
  int painted=0;

//  double dX, dY;

  TextInBoxMode_t displaymode = {0};
  displaymode.NoSetFont = 1;

  #if 0
  double screenrange = GetApproxScreenRange();
  double scalefact = screenrange/6000.0; // FIX 100820
  #endif




  HFONT  oldfont = (HFONT)SelectObject(hDC, LK8MapFont);

  for (i=0,painted=0; i<FLARM_MAX_TRAFFIC; i++) {

	// limit to 10 icons map traffic
	if (painted>=10) {
		i=FLARM_MAX_TRAFFIC;
		continue;
	}

	if ( (DrawInfo.FLARM_Traffic[i].ID !=0) && (DrawInfo.FLARM_Traffic[i].Status != LKT_ZOMBIE) ) {

		painted++;

		double target_lon;
		double target_lat;

		target_lon = DrawInfo.FLARM_Traffic[i].Longitude;
		target_lat = DrawInfo.FLARM_Traffic[i].Latitude;

		#if (0) // No scaling, wrong
		if ((EnableFLARMMap==2)&&(scalefact>1.0)) {

			double distance;
			double bearing;

			DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, target_lat, target_lon, &distance, &bearing);
			FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, bearing, distance*scalefact, &target_lat, &target_lon);
		}
		#endif
      
		POINT sc, sc_name, sc_av;
		LatLon2Screen(target_lon, target_lat, sc);

		sc_name = sc;

		sc_name.y -= NIBLSCALE(16);
		sc_av = sc_name;

		wsprintf(lbuffer,_T(""));
		if (DrawInfo.FLARM_Traffic[i].Cn && DrawInfo.FLARM_Traffic[i].Cn[0]!=_T('?')) { // 100322
			_tcscat(lbuffer,DrawInfo.FLARM_Traffic[i].Cn);
		}
		if (DrawInfo.FLARM_Traffic[i].Average30s>=0.1) {
			if (_tcslen(lbuffer) >0)
				_stprintf(lbuffer,_T("%s:%.1f"),lbuffer,LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
			else
				_stprintf(lbuffer,_T("%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s);
		}

		displaymode.Border=1;

		if (_tcslen(lbuffer)>0)
		TextInBox(hDC, lbuffer, sc.x+tscaler, sc.y+tscaler, 0, &displaymode, false);

		// red circle
		if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) {
			DrawBitmapIn(hDC, sc, hFLARMTraffic,true);
		}
#if 0
		Arrow[0].x = -4;
		Arrow[0].y = 5;
		Arrow[1].x = 0;
		Arrow[1].y = -6;
		Arrow[2].x = 4;
		Arrow[2].y = 5;
		Arrow[3].x = 0;
		Arrow[3].y = 2;
		Arrow[4].x = -4;
		Arrow[4].y = 5;
#endif

		Arrow[0].x = scaler[0];
		Arrow[0].y = scaler[1];
		Arrow[1].x = 0;
		Arrow[1].y = scaler[2];
		Arrow[2].x = scaler[3];
		Arrow[2].y = scaler[1];
		Arrow[3].x = 0;
		Arrow[3].y = scaler[4];
		Arrow[4].x = scaler[0];
		Arrow[4].y = scaler[1];
/*
		switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				SelectObject(hDC, yellowBrush);
				break;
			case LKT_ZOMBIE:
				SelectObject(hDC, redBrush);
				break;
			default:
				SelectObject(hDC, greenBrush);
				break;
		}
*/
		  /*************************************************************************
		   * calculate climb color
		   *************************************************************************/

		  int iVarioIdx = (int)(2*DrawInfo.FLARM_Traffic[i].Average30s  -0.5)+NO_VARIO_COLORS/2;
		  if(iVarioIdx < 0) iVarioIdx =0;
		  if(iVarioIdx >= NO_VARIO_COLORS) iVarioIdx =NO_VARIO_COLORS-1;
		  SelectObject(hDC, *variobrush[iVarioIdx]);

		  switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321
			case LKT_GHOST:
				Rectangle(hDC, sc.x-iRectangleSize,  sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize);
				break;
			case LKT_ZOMBIE:
				Circle(hDC,  sc.x,  sc.x, iCircleSize, rc, true, true );
				break;
			default:
				PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle);
				Polygon(hDC,Arrow,5);
				break;
		  }

	}
  }

  SelectObject(hDC, oldfont);
  SelectObject(hDC, hpold);

}
Пример #27
0
void MapWindow::DrawAirspaceLabels(HDC hdc, const RECT rc, const POINT Orig_Aircraft)
{
  static short int label_sequencing_divider = 0;
  CAirspaceList::const_iterator it;
  const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetAirspacesForWarningLabels();
  
  if (label_sequencing_divider) --label_sequencing_divider;

  // Draw warning position and label on top of all airspaces
  if (1) {
  CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
  for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) {
        if ((*it)->WarningLevel() > awNone) {
          POINT sc;
          double lon;
          double lat;
          int vdist;
          AirspaceWarningDrawStyle_t vlabeldrawstyle, hlabeldrawstyle;
          bool distances_ready = (*it)->GetWarningPoint(lon, lat, hlabeldrawstyle, vdist, vlabeldrawstyle);
          TCHAR hbuf[NAME_SIZE+16], vDistanceText[16];
          TextInBoxMode_t TextDisplayMode = {0};
          bool hlabel_draws = false;
          bool vlabel_draws = false;
          
          // Horizontal warning point
          if (distances_ready && (hlabeldrawstyle > awsHidden) && PointVisible(lon, lat)) {

              LatLon2Screen(lon, lat, sc);
              DrawBitmapIn(hdc, sc, hAirspaceWarning,true);
              
              Units::FormatUserAltitude(vdist, vDistanceText, sizeof(vDistanceText)/sizeof(vDistanceText[0]));
              _tcscpy(hbuf, (*it)->Name());
              wcscat(hbuf, TEXT(" "));
              wcscat(hbuf, vDistanceText);
              
              switch (hlabeldrawstyle) {
                default:
                case awsHidden:
                case awsBlack:
                  TextDisplayMode.Color = RGB_BLACK;
                  break;
                case awsAmber:
                  TextDisplayMode.Color = RGB_ORANGE;
                  break;
                case awsRed:
                  TextDisplayMode.Color = RGB_RED;
                  break;
              } // sw
              TextDisplayMode.SetTextColor = 1;
              TextDisplayMode.AlligneCenter = 1;
              if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
                  TextDisplayMode.Border = 1;
              } else {
		  if (TextDisplayMode.Color==RGB_BLACK)
                     TextDisplayMode.WhiteBold = 0; // no black outline for black background..
                  else
                     TextDisplayMode.WhiteBold = 1; // outlined  
              }

              hlabel_draws = TextInBox(hdc, &rc, hbuf, sc.x, sc.y+NIBLSCALE(15), 0, &TextDisplayMode, true);
           }
           
          // Vertical warning point
          if (distances_ready && vlabeldrawstyle > awsHidden) {

              //DrawBitmapIn(hdc, Orig_Aircraft, hAirspaceWarning);
              
              Units::FormatUserAltitude(vdist, vDistanceText, sizeof(vDistanceText)/sizeof(vDistanceText[0]));
              _tcscpy(hbuf, (*it)->Name());
              wcscat(hbuf, TEXT(" "));
              wcscat(hbuf, vDistanceText);
              
              switch (vlabeldrawstyle) {
                default:
                case awsHidden:
                case awsBlack:
                  TextDisplayMode.Color = RGB_BLACK;
                  break;
                case awsAmber:
                  TextDisplayMode.Color = RGB_ORANGE;
                  break;
                case awsRed:
                  TextDisplayMode.Color = RGB_RED;
                  break;
              } // sw
              TextDisplayMode.SetTextColor = 1;
              TextDisplayMode.AlligneCenter = 1;
              if ( (MapBox == (MapBox_t)mbBoxed) || (MapBox == (MapBox_t)mbBoxedNoUnit)) {
                  TextDisplayMode.Border = 1;
              } else {
		  if (TextDisplayMode.Color==RGB_BLACK)
                     TextDisplayMode.WhiteBold = 0; // no black outline for black background..
                  else
                     TextDisplayMode.WhiteBold = 1; // outlined  
              }

              vlabel_draws = TextInBox(hdc, &rc, hbuf, Orig_Aircraft.x, Orig_Aircraft.y+NIBLSCALE(15), 0, &TextDisplayMode, true);
           }
           if (!label_sequencing_divider) CAirspaceManager::Instance().AirspaceWarningLabelPrinted(**it, hlabel_draws || vlabel_draws);
           
         }// if warnlevel>awnone
  }//for
  }// if(1) mutex
  if (!label_sequencing_divider) label_sequencing_divider=3;		// Do label sequencing slower than update rate
}
Пример #28
0
//
// Final Glide Bar, revised for variometer gauge
//
void MapWindow::DrawFinalGlide(HDC hDC, const RECT rc)
{

    SIZE           TextSize;

    if ((GlideBarMode == (GlideBarMode_t)gbDisabled)) {
        GlideBarOffset=0;
        return;
    }

    POINT GlideBar[6] = { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };
    POINT GlideBar0[6] = { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };

    HPEN hpOld;
    HBRUSH hbOld;

    TCHAR Value[10];

    int Offset;
    int Offset0;
    int i;
    int lkVarioOffset=0, minBar, maxBar;

    if (LKVarioBar)
        lkVarioOffset=LKVarioSize+NIBLSCALE(2); //@ 091114

    // 091114
    switch(ScreenSize) {
    case (ScreenSize_t)ss480x234:
    case (ScreenSize_t)ss480x272:
    case (ScreenSize_t)ss720x408:
        minBar=-40;
        maxBar=40;
        break;
    case (ScreenSize_t)ss800x480:
    case (ScreenSize_t)ss400x240:
        minBar=-45;
        maxBar=45;
        break;
    default:
        minBar=-50; // was 60
        maxBar=50;
        break;
    }

    LockTaskData();  // protect from external task changes

    bool invalidbar=false;
#if 101004
    int barindex;
    barindex=GetOvertargetIndex();
    if (barindex>=0) {
#else
    if (ValidTaskPoint(ActiveWayPoint)) {
#endif

        const int y0 = ( (rc.bottom - rc.top )/2)+rc.top;

#if 110609
        if ( ValidTaskPoint(1) && OvertargetMode == OVT_TASK && GlideBarMode == (GlideBarMode_t)gbFinish ) {
            // Before the start, there is no task altitude available!
            if (DerivedDrawInfo.ValidStart) {
                Offset = ((int)DerivedDrawInfo.TaskAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.TaskAltitudeDifference0)/8;
            } else {
                // In this case, print an invalid bar
                invalidbar=true;
                Offset=0;
                Offset0=0;
            }
        } else {
            Offset=(int)WayPointCalc[barindex].AltArriv[AltArrivMode];
            Offset0=Offset;
        }
#else
        // This is wrong, we are painting values relative to MC and ignoring safetyMC
        if (OvertargetMode != OVT_TASK) { //@ 101004
            Offset=(int)WayPointCalc[barindex].AltArriv[AltArrivMode];
            Offset0=Offset;
        } else {
            // 60 units is size, div by 8 means 60*8 = 480 meters.
            if ( (GlideBarMode == (GlideBarMode_t)gbFinish)) {
                Offset = ((int)DerivedDrawInfo.TaskAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.TaskAltitudeDifference0)/8;
            } else {
                Offset = ((int)DerivedDrawInfo.NextAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.NextAltitudeDifference0)/8;
            }
        }
#endif

        // TODO feature: should be an angle if in final glide mode

        if(Offset > maxBar) Offset = maxBar;
        if(Offset < minBar) Offset = minBar;
        Offset = IBLSCALE(Offset);
        if(Offset<0) {
            GlideBar[1].y = NIBLSCALE(9);
        }

        if(Offset0 > maxBar) Offset0 = maxBar;
        if(Offset0 < minBar) Offset0 = minBar;
        Offset0 = IBLSCALE(Offset0);
        if(Offset0<0) {
            GlideBar0[1].y = NIBLSCALE(9);
        }

        for(i=0; i<6; i++) {
            GlideBar[i].y += y0;
            // if vario activated
            GlideBar[i].x = IBLSCALE(GlideBar[i].x)+rc.left+lkVarioOffset; //@ 091114
        }
        GlideBar[0].y -= Offset;
        GlideBar[1].y -= Offset;
        GlideBar[2].y -= Offset;

        for(i=0; i<6; i++) {
            GlideBar0[i].y += y0;
            GlideBar0[i].x = IBLSCALE(GlideBar0[i].x)+rc.left+lkVarioOffset; //@ 091114
        }
        GlideBar0[0].y -= Offset0;
        GlideBar0[1].y -= Offset0;
        GlideBar0[2].y -= Offset0;

        if ((Offset<0)&&(Offset0<0)) {
            // both below
            if (Offset0!= Offset) {
                int dy = (GlideBar0[0].y-GlideBar[0].y) +(GlideBar0[0].y-GlideBar0[3].y);
                dy = max(NIBLSCALE(3), dy);
                GlideBar[3].y = GlideBar0[0].y-dy;
                GlideBar[4].y = GlideBar0[1].y-dy;
                GlideBar[5].y = GlideBar0[2].y-dy;

                GlideBar0[0].y = GlideBar[3].y;
                GlideBar0[1].y = GlideBar[4].y;
                GlideBar0[2].y = GlideBar[5].y;
            } else {
                Offset0 = 0;
            }

        } else if ((Offset>0)&&(Offset0>0)) {
            // both above
            GlideBar0[3].y = GlideBar[0].y;
            GlideBar0[4].y = GlideBar[1].y;
            GlideBar0[5].y = GlideBar[2].y;

            if (abs(Offset0-Offset)<NIBLSCALE(4)) {
                Offset= Offset0;
            }
        }

        // draw actual glide bar

        if (Offset<=0) {
            hpOld = (HPEN)SelectObject(hDC, hpFinalGlideBelow);
            hbOld = (HBRUSH)SelectObject(hDC, LKBrush_Red);
        } else {
            hpOld = (HPEN)SelectObject(hDC, hpFinalGlideAbove);
            hbOld = (HBRUSH)SelectObject(hDC, LKBrush_Green);
        }
        Polygon(hDC,GlideBar,6);

        // in case of invalid bar because finish mode with real task but no valid start, we skip
        if (invalidbar) {
            _tcscpy(Value,_T("---"));
            goto _skipout;
        }

        // draw glide bar at mc 0 and X  only for OVT_TASK 101004
        // we dont have mc0 calc ready for other overtargets, not granted at least
        if (OvertargetMode == OVT_TASK) {
            if (Offset0<=0) {
                SelectObject(hDC, hpFinalGlideBelow);
                SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
            } else {
                SelectObject(hDC, hpFinalGlideAbove);
                SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
            }
            if (Offset!=Offset0) {
                Polygon(hDC,GlideBar0,6);
            }


            // Draw an X  on final glide bar if unreachable at current Mc
            if ( (GlideBarMode == (GlideBarMode_t)gbFinish) ) {
                if ((DerivedDrawInfo.TaskTimeToGo>0.9*ERROR_TIME) ||
                        ((MACCREADY<0.01) && (DerivedDrawInfo.TaskAltitudeDifference<0))) {
                    SelectObject(hDC, LKPen_White_N2);
                    POINT Cross[4] = { {-5, -5}, { 5,  5}, {-5,  5}, { 5, -5} };
                    for (i=0; i<4; i++) {
                        Cross[i].x = IBLSCALE(Cross[i].x+9)+lkVarioOffset; //@ 091114
                        Cross[i].y = IBLSCALE(Cross[i].y+9)+y0;
                    }
                    Polygon(hDC,Cross,2);
                    Polygon(hDC,&Cross[2],2);
                }
            } else {
                if ((MACCREADY<0.01) && (DerivedDrawInfo.NextAltitudeDifference<0)) {
                    SelectObject(hDC, LKPen_White_N2);
                    POINT Cross[4] = { {-5, -5}, { 5,  5}, {-5,  5}, { 5, -5} };
                    for (i=0; i<4; i++) {
                        Cross[i].x = IBLSCALE(Cross[i].x+9)+lkVarioOffset;
                        Cross[i].y = IBLSCALE(Cross[i].y+9)+y0;
                    }
                    Polygon(hDC,Cross,2);
                    Polygon(hDC,&Cross[2],2);
                }
            }
        }

        // draw boxed value in the center
        if (OvertargetMode == OVT_TASK ) { //@ 101004
            // A task is made of at least 2 tps, otherwise its a goto
            if (( (GlideBarMode == (GlideBarMode_t)gbFinish) && ValidTaskPoint(1)) ) {
                if(ISPARAGLIDER && DerivedDrawInfo.TaskAltitudeDifference > 0.0) {
                    if ( (ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeArrival) <ALTDIFFLIMIT) //@ 091114
                        _stprintf(Value,TEXT(" --- "));
                    else
                        _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeArrival);
                } else {
                    if ( (ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeDifference) <ALTDIFFLIMIT) //@ 091114
                        _stprintf(Value,TEXT(" --- "));
                    else
                        _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeDifference);
                }
            } else {
                if ( (ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]) < ALTDIFFLIMIT)
                    _stprintf(Value,TEXT(" --- "));
                else
                    _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]);
                /*
                 * Well this was the reason why the glidebar value was out of sync with overlays
                if ( (ALTITUDEMODIFY*DerivedDrawInfo.NextAltitudeDifference) < ALTDIFFLIMIT) //@ 091114
                	_stprintf(Value,TEXT(" --- "));
                else
                	_stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.NextAltitudeDifference);
                */
            }
        } else {
            if ( (ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]) < ALTDIFFLIMIT)
                _stprintf(Value,TEXT(" --- "));
            else
                _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]);
        }

_skipout:
        // in case of invalidbar we get here with Offset 0

        if (Offset>=0) {
            Offset = GlideBar[2].y+Offset+NIBLSCALE(5);
        } else {
            if (Offset0>0) {
                Offset = GlideBar0[1].y-NIBLSCALE(15);
            } else {
                Offset = GlideBar[2].y+Offset-NIBLSCALE(15);
            }
        }
        // VENTA10
        GetTextExtentPoint(hDC, Value, _tcslen(Value), &TextSize);
        GlideBarOffset=max(NIBLSCALE(11),(int)TextSize.cx) - NIBLSCALE(2);

        TextInBoxMode_t TextInBoxMode = {0};
        TextInBoxMode.Border = true;          //={1|8};
        TextInBoxMode.Reachable = true;
        // boxed numbers are a bit too much on the left, so increase the offset
        TextInBox(hDC, &rc,Value, lkVarioOffset+NIBLSCALE(1), (int)Offset, 0, &TextInBoxMode); //@ 091114

        SelectObject(hDC, hbOld);
        SelectObject(hDC, hpOld);
    } else GlideBarOffset=0; 	// 091125 BUGFIX glidebaroffset is zero when no task point
    {
        UnlockTaskData();
    }

}
Пример #29
0
/**
 * Draws the GliderLink traffic icons onto the given canvas
 * @param canvas Canvas for drawing
 */
void
MapWindow::DrawGLinkTraffic(Canvas &canvas,
                            const PixelPoint aircraft_pos) const
{
#ifdef ANDROID

  // Return if FLARM icons on moving map are disabled
  if (!GetMapSettings().show_flarm_on_map)
    return;

  const GliderLinkTrafficList &traffic = Basic().glink_data.traffic;
  if (traffic.IsEmpty())
    return;

  const MoreData &basic = Basic();

  const WindowProjection &projection = render_projection;

  canvas.Select(*traffic_look.font);

  // Circle through the GliderLink targets
  for (const auto &traf : traffic.list) {

    // Save the location of the target
    GeoPoint target_loc = traf.location;

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

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

    // Draw the callsign above the icon
    sc_name = sc;
    sc_name.x -= Layout::Scale(10);
    sc_name.y -= Layout::Scale(15);

    // Draw the average climb to the right of the icon
    sc_av = sc;
    sc_av.x += Layout::Scale(10);
    sc_av.y -= Layout::Scale(8);

    // Location of altitude label
    sc_alt = sc;
    sc_alt.x -= Layout::Scale(10);
    sc_alt.y -= Layout::Scale(0);

    TextInBoxMode mode;
    mode.shape = LabelShape::OUTLINED;
    mode.align = TextInBoxMode::Alignment::RIGHT;

    // If callsign/name available draw it to the canvas
    if (traf.HasName() && !StringIsEmpty(traf.name))
      TextInBox(canvas, traf.name, sc_name.x, sc_name.y,
                mode, GetClientRect());

    if (traf.climb_rate_received) {

      // If average climb data available draw it to the canvas
      TCHAR label_avg[100];
      FormatUserVerticalSpeed(traf.climb_rate,
                                     label_avg, false);
      mode.align = TextInBoxMode::Alignment::LEFT;
      TextInBox(canvas, label_avg, sc_av.x, sc_av.y, mode, GetClientRect());
    }

    // use GPS altitude to be consistent with GliderLink
    if(basic.gps_altitude_available && traf.altitude_received
        && fabs(double(traf.altitude) - basic.gps_altitude) >= 100.0) {
      // If average climb data available draw it to the canvas
      TCHAR label_alt[100];
      double alt = (double(traf.altitude) - basic.gps_altitude) / 100.0;
      FormatRelativeUserAltitude(alt, label_alt, false);

      mode.align = TextInBoxMode::Alignment::RIGHT;
      TextInBox(canvas, label_alt, sc_alt.x, sc_alt.y, mode, GetClientRect());
    }

    TrafficRenderer::Draw(canvas, traffic_look, traf,
                          traf.track - projection.GetScreenAngle(), sc);
  }
#endif
}
Пример #30
0
/**
 * Draws the FLARM traffic icons onto the given canvas
 * @param canvas Canvas for drawing
 */
void
MapWindow::DrawFLARMTraffic(Canvas &canvas,
                            const PixelPoint 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 TrafficList &flarm = Basic().flarm.traffic;
  if (flarm.IsEmpty())
    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() > 7300)
    return;

  canvas.Select(*traffic_look.font);

  // Circle through the FLARM targets
  for (auto it = flarm.list.begin(), end = flarm.list.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
    PixelPoint 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.shape = LabelShape::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, GetClientRect());

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

    auto color = FlarmFriends::GetFriendColor(traffic.id);
    TrafficRenderer::Draw(canvas, traffic_look, traffic,
                          traffic.track - projection.GetScreenAngle(),
                          color, sc);
  }
}