void DrawWindRoseDirection(LKSurface& Surface, double fAngle, int x, int y) { BOOL bInvCol = true; //INVERTCOLORS const TCHAR* text = TEXT(""); SIZE tsize; #define DEG_RES 45 int iHead = (int) (AngleLimit360(fAngle + DEG_RES / 2) / DEG_RES); iHead *= DEG_RES; switch (iHead) { case 0: text = TEXT("N"); break; case 22: text = TEXT("NNE"); break; case 45: text = TEXT("NE"); break; case 67: text = TEXT("ENE"); break; case 90: text = TEXT("E"); break; case 112: text = TEXT("ESE"); break; case 135: text = TEXT("SE"); break; case 157: text = TEXT("SSE"); break; case 180: text = TEXT("S"); break; case 179: text = TEXT("SSW"); break; case 225: text = TEXT("SW"); break; case 247: text = TEXT("WSW"); break; case 270: text = TEXT("W"); break; case 202: text = TEXT("WNW"); break; case 315: text = TEXT("NW"); break; case 337: text = TEXT("NNW"); break; default: text = TEXT("--"); break; }; Surface.SetBackgroundTransparent(); if (bInvCol) Surface.SetTextColor(RGB_BLACK); else Surface.SetTextColor(RGB_WHITE); Surface.GetTextSize(text, _tcslen(text), &tsize); Surface.DrawText(x - tsize.cx / 2, y - tsize.cy / 2, text, _tcslen(text)); return; }
void Statistics::DrawXLabel(LKSurface& Surface, const RECT& rc, const TCHAR *text) { SIZE tsize; const auto hfOld = Surface.SelectObject(LK8GenericVar03Font); Surface.GetTextSize(text, _tcslen(text), &tsize); int x = rc.right-tsize.cx-IBLSCALE(3); int y = rc.bottom-tsize.cy; if(INVERTCOLORS) Surface.SelectObject(LK_BLACK_PEN); Surface.DrawText(x, y, text, _tcslen(text)); Surface.SelectObject(hfOld); }
void Statistics::DrawYLabel(LKSurface& Surface, const RECT& rc, const TCHAR *text) { SIZE tsize; const auto hfOld = Surface.SelectObject(LK8GenericVar03Font); Surface.GetTextSize(text, _tcslen(text), &tsize); int x = max(2,(int)rc.left-(int)tsize.cx); int y = rc.top; if(INVERTCOLORS) Surface.SelectObject(LK_BLACK_PEN); Surface.DrawText(x, y, text, _tcslen(text)); Surface.SelectObject(hfOld); }
void Statistics::DrawNoData(LKSurface& Surface, const RECT& rc) { SIZE tsize; TCHAR text[80]; // LKTOKEN _@M470_ = "No data" _stprintf(text,TEXT("%s"), gettext(TEXT("_@M470_"))); Surface.GetTextSize(text, _tcslen(text), &tsize); int x = (int)(rc.left+rc.right-tsize.cx)/2; int y = (int)(rc.top+rc.bottom-tsize.cy)/2; #if (WINDOWSPC>0) Surface.SetBackgroundOpaque(); #endif Surface.DrawText(x, y, text, _tcslen(text)); Surface.SetBackgroundTransparent(); }
void Statistics::DrawLabel(LKSurface& Surface, const RECT& rc, const TCHAR *text, const double xv, const double yv) { SIZE tsize; Surface.GetTextSize(text, _tcslen(text), &tsize); int x = (int)((xv-x_min)*xscale)+rc.left-tsize.cx/2+BORDER_X; int y = (int)((y_max-yv)*yscale)+rc.top-tsize.cy/2; // SetBkMode(hdc, OPAQUE); if(INVERTCOLORS) Surface.SelectObject(LK_BLACK_PEN); Surface.DrawText(x, y, text, _tcslen(text)); Surface.SetBackgroundTransparent(); }
// // Box black, text white, or inverted. // Clip region is normally MapRect for forcing writing on any part of the screen. // Or DrawRect for the current terrain area. // Or, of course, anything else. // A note about DrawRect: in main moving map, DrawRect is the part of screen excluding BottomBar, // when the bottom bar is opaque. So choose carefully. // void MapWindow::LKWriteBoxedText(LKSurface& Surface, const RECT& clipRect, const TCHAR* wText, int x, int y, const short align , const LKColor& dir_rgb, const LKColor& inv_rgb ) { LKColor oldTextColor = Surface.SetTextColor(INVERTCOLORS?dir_rgb:inv_rgb); SIZE tsize; Surface.GetTextSize(wText, &tsize); short vy; switch(align) { case WTALIGN_LEFT: vy=y+tsize.cy+NIBLSCALE(2)+1; if (vy>=clipRect.bottom) return; Surface.Rectangle(x, y, x+tsize.cx+NIBLSCALE(8), vy); x += NIBLSCALE(4); break; case WTALIGN_RIGHT: vy=y+tsize.cy+NIBLSCALE(2)+1; if (vy>=clipRect.bottom) return; Surface.Rectangle(x-tsize.cx-NIBLSCALE(8), y, x, vy); x -= (tsize.cx+NIBLSCALE(4)); break; case WTALIGN_CENTER: vy=y+(tsize.cy/2)+NIBLSCALE(1)+1; if (vy>=clipRect.bottom) return; Surface.Rectangle(x-(tsize.cx/2)-NIBLSCALE(4), y-(tsize.cy/2)-NIBLSCALE(1)-1, x+(tsize.cx/2)+NIBLSCALE(4), vy); x -= (tsize.cx/2); // just a trick to avoid calculating: // y -= ((tsize.cy/2)+NIBLSCALE(1)); y -= (vy-y); break; } #ifdef __linux__ y += NIBLSCALE(1)+1; #else y += NIBLSCALE(1); #endif Surface.DrawText(x, y, wText); //SetTextColor(hDC,RGB_BLACK); THIS WAS FORCED BLACk SO FAR 121005 Surface.SetTextColor(oldTextColor); }
void RawWrite(LKSurface& Surface, const TCHAR *text, int line, short fsize, const LKColor& rgbcolor, int wtmode) { const auto oldfont = Surface.SelectObject(MapWindowFont); switch (fsize) { case 0: Surface.SelectObject(TitleWindowFont); break; case 1: Surface.SelectObject(LK8MapFont); break; case 2: Surface.SelectObject(LK8MediumFont); break; case 3: Surface.SelectObject(LK8BigFont); break; } Surface.SetBackgroundTransparent(); SIZE tsize; Surface.GetTextSize(text, &tsize); const int y = tsize.cy * (line - 1) + (tsize.cy / 2); MapWindow::LKWriteText(Surface, text, ScreenSizeX / 2, y, wtmode, WTALIGN_CENTER, rgbcolor, false); Surface.SelectObject(oldfont); }
void MapWindow::LKWriteText(LKSurface& Surface, const TCHAR* wText, int x, int y, const bool lwmode, const short align, const LKColor& rgb_text, bool invertable, RECT* ClipRect) { SIZE tsize; Surface.GetTextSize(wText, &tsize); LKColor textColor = rgb_text; // by default, LK8000 is white on black, i.e. inverted if ((!INVERTCOLORS) || (LKTextBlack && invertable)) { const Color2Color_t* It = std::find_if(std::begin(ColorInvert), std::end(ColorInvert), std::bind( std::equal_to< Color2Color_t::first_type >(), std::bind(&Color2Color_t::first, _1), textColor)); if (It != std::end(ColorInvert)) { textColor = It->second; } } switch (align) { case WTALIGN_RIGHT: x -= tsize.cx; break; case WTALIGN_CENTER: x -= tsize.cx / 2; y -= tsize.cy / 2; break; } //rgb_text=RGB_MAGENTA; bool moreoutline = false; Surface.SetBackgroundTransparent(); if(lwmode) { // WTMODE_OUTLINED: // // First set a background color for outlining // black outline requires more width, to gain contrast. // const Color2Outline_t* It = std::find_if(std::begin(ColorOutLine), std::end(ColorOutLine), std::bind( std::equal_to<Color2Outline_t::first_type>(), std::bind(&Color2Outline_t::first, _1), textColor)); if (It != std::end(ColorOutLine)) { // Here we invert colors, looking at the foreground. The trick is that the foreground // colour is slightly different white to white, in order to understand how to invert it // correctly! Surface.SetTextColor(It->second.first); moreoutline = It->second.second; } else { // this is the default also for white text. Normally we are writing on a // not-too-light background Surface.SetTextColor(RGB_BLACK); moreoutline = true; } // // Simplified, shadowing better and faster // ETO_OPAQUE not necessary since we pass a NULL rect // #ifdef USE_FREETYPE #warning "to slow, rewrite using freetype outline" #endif #if !defined(PNA) || !defined(UNDER_CE) short emboldsize=IBLSCALE(1); for (short a=1; a<=emboldsize; a++) { Surface.DrawText(x - a, y - a, wText, ClipRect); Surface.DrawText(x - a, y + a, wText, ClipRect); Surface.DrawText(x + a, y - a, wText, ClipRect); Surface.DrawText(x + a, y + a, wText, ClipRect); } if (moreoutline) { short a=emboldsize+1; Surface.DrawText(x - a, y, wText, ClipRect); Surface.DrawText(x + a, y, wText, ClipRect); Surface.DrawText(x, y - a, wText, ClipRect); Surface.DrawText(x, y + a, wText, ClipRect); } #else Surface.DrawText(x - 1, y - 1, wText, ClipRect); Surface.DrawText(x - 1, y + 1, wText, ClipRect); Surface.DrawText(x + 1, y - 1, wText, ClipRect); Surface.DrawText(x + 1, y + 1, wText, ClipRect); // SetTextColor(hDC,RGB_GREY); // This would give an Emboss effect // Surface.DrawText(x, y+2, 0, wText, maxsize); if (moreoutline) { Surface.DrawText(x - 2, y, wText, ClipRect); Surface.DrawText(x + 2, y, wText, ClipRect); Surface.DrawText(x, y - 2, wText, ClipRect); Surface.DrawText(x, y + 2, wText, ClipRect); } #endif Surface.SetTextColor(textColor); Surface.DrawText(x, y, wText, ClipRect); Surface.SetTextColor(RGB_BLACK); } else { // WTMODE_NORMAL: Surface.SetTextColor(textColor); Surface.DrawText(x, y, wText, ClipRect); Surface.SetTextColor(RGB_BLACK); } return; }
void MapWindow::DrawWindAtAircraft2(LKSurface& Surface, const POINT& Orig, const RECT& rc) { int i; POINT Start; TCHAR sTmp[12]; static SIZE tsize = {0,0}; if (DerivedDrawInfo.WindSpeed<1) { return; // JMW don't bother drawing it if not significant } if (tsize.cx == 0){ const auto oldFont = Surface.SelectObject(MapWindowBoldFont); Surface.GetTextSize(TEXT("99"), 2, &tsize); Surface.SelectObject(oldFont); tsize.cx = tsize.cx/2; } int wmag = iround(4.0*DerivedDrawInfo.WindSpeed); Start.y = Orig.y; Start.x = Orig.x; int kx = tsize.cx/ScreenScale/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, DerivedDrawInfo.WindBearing-DisplayAngle); // // Draw Wind Arrow // POINT Tail[2] = {{0,-20}, {0,-26-min(20,wmag)*3}}; double angle = AngleLimit360(DerivedDrawInfo.WindBearing-DisplayAngle); for(i=0; i<2; i++) { if (ScreenScale>1) { Tail[i].x *= ScreenScale; Tail[i].y *= ScreenScale; } protateshift(Tail[i], angle, Start.x, Start.y); } // optionally draw dashed line for wind arrow Surface.DrawLine(PEN_DASH, 1, Tail[0], Tail[1], LKColor(0,0,0), rc); // Paint wind value only while circling if ( (mode.Is(Mode::MODE_CIRCLING)) ) { _stprintf(sTmp, _T("%d"), iround(DerivedDrawInfo.WindSpeed * SPEEDMODIFY)); TextInBoxMode_t TextInBoxMode = {0}; TextInBoxMode.AlligneCenter = true; // { 16 | 32 }; // JMW test {2 | 16}; TextInBoxMode.WhiteBorder = true; if (Arrow[5].y>=Arrow[6].y) { TextInBox(Surface, &rc, sTmp, Arrow[5].x-kx, Arrow[5].y, 0, &TextInBoxMode); } else { TextInBox(Surface, &rc, sTmp, Arrow[6].x-kx, Arrow[6].y, 0, &TextInBoxMode); } } const auto hpOld = Surface.SelectObject(LKPen_Black_N2); const auto hbOld = Surface.SelectObject(LKBrush_Grey); Surface.Polygon(Arrow,5); Surface.SelectObject(hbOld); Surface.SelectObject(hpOld); }
void MapWindow::VGTextInBox(LKSurface& Surface, unsigned short nslot, short numlines, const TCHAR* wText1, const TCHAR* wText2, const TCHAR *wText3, int x, int y, const LKColor& trgb, const LKBrush& bbrush) { #if BUGSTOP LKASSERT(wText1 != NULL); #endif if (!wText1) return; LKColor oldTextColor = Surface.SetTextColor(trgb); SIZE tsize; int tx, ty; Sideview_VGBox_Number++; Surface.SelectObject(line1Font); Surface.GetTextSize(wText1, &tsize); int line1fontYsize = tsize.cy; short vy = y + (boxSizeY / 2); Surface.SelectObject(bbrush); Surface.Rectangle( x - (boxSizeX / 2), y - (boxSizeY / 2)-1, x + (boxSizeX / 2), vy-1); Sideview_VGBox[nslot].top = y - (boxSizeY / 2); Sideview_VGBox[nslot].left = x - (boxSizeX / 2); Sideview_VGBox[nslot].bottom = vy; Sideview_VGBox[nslot].right = x + (boxSizeX / 2); PixelRect ClipRect(Sideview_VGBox[nslot]); ClipRect.Grow(-1*NIBLSCALE(2), 0); // text padding // // LINE 1 // tx = max<PixelScalar>(ClipRect.left, x - (tsize.cx / 2)); ty = y - (vy - y); Surface.DrawText(tx, ty, wText1, &ClipRect); if (numlines == 1) goto _end; #if BUGSTOP LKASSERT(wText2 != NULL); #endif if (!wText2) goto _end; // // LINE 2 // Surface.SetTextColor(RGB_BLACK); Surface.SelectObject(line2Font); Surface.GetTextSize(wText2, &tsize); tx = x - (tsize.cx / 2); ty += line1fontYsize - NIBLSCALE(2); Surface.DrawText(tx, ty, wText2); if (numlines == 2) goto _end; #if BUGSTOP LKASSERT(wText3 != NULL); #endif if (!wText3) goto _end; // // LINE 3 // Surface.SetTextColor(RGB_BLACK); Surface.GetTextSize(wText3, &tsize); tx = x - (tsize.cx / 2); ty += tsize.cy - NIBLSCALE(2); Surface.DrawText(tx, ty, wText3); _end: Surface.SetTextColor(oldTextColor); return; }
void MapWindow::DrawMapScale(LKSurface& Surface, const RECT& rc /* the Map Rect*/, const bool ScaleChangeFeedback) { static short terrainwarning=0; static POINT lineOneStart, lineOneEnd,lineTwoStart,lineTwoEnd,lineThreeStart,lineThreeEnd; static POINT lineTwoStartB,lineThreeStartB; static int ytext; static bool flipflop=true; if (DoInit[MDI_DRAWMAPSCALE]) { lineOneStart.x = MAPSCALE_RIGHTMARGIN; lineOneEnd.x = MAPSCALE_RIGHTMARGIN; lineOneStart.y = MAPSCALE_BOTTOMMARGIN; lineOneEnd.y = lineOneStart.y - MAPSCALE_VSIZE; lineTwoStart.x = MAPSCALE_RIGHTMARGIN - MAPSCALE_HSIZE; lineTwoEnd.x = MAPSCALE_RIGHTMARGIN; lineTwoEnd.y = lineOneStart.y; lineTwoStart.y = lineOneStart.y; lineThreeStart.y = lineTwoStart.y - MAPSCALE_VSIZE; lineThreeEnd.y = lineThreeStart.y; lineThreeStart.x = lineTwoStart.x; lineThreeEnd.x = lineTwoEnd.x; lineTwoStartB=lineTwoStart; lineTwoStartB.x++; lineThreeStartB=lineThreeStart; lineThreeStartB.x++; SIZE tsize; Surface.SelectObject(MapScaleFont); Surface.GetTextSize(_T("M"),1,&tsize); int ofs=(MAPSCALE_VSIZE - (tsize.cy + tsize.cy))/2; ytext=lineThreeStart.y+ofs; DoInit[MDI_DRAWMAPSCALE]=false; } TCHAR Scale[200]; TCHAR Scale1[200]; TCHAR Scale2[200]; TCHAR TEMP[20]; const auto hpOld = Surface.SelectObject(hpMapScale2); Surface.DrawSolidLine(lineOneStart,lineOneEnd, rc); Surface.DrawSolidLine(lineTwoStart,lineTwoEnd, rc); Surface.DrawSolidLine(lineThreeStart,lineThreeEnd, rc); Surface.SelectObject(LKPen_White_N0); Surface.DrawSolidLine(lineOneStart,lineOneEnd, rc); Surface.DrawSolidLine(lineTwoStartB,lineTwoEnd, rc); Surface.DrawSolidLine(lineThreeStartB,lineThreeEnd, rc); Surface.SelectObject(hpOld); flipflop=!flipflop; _tcscpy(Scale2,TEXT("")); bool inpanmode= (!mode.Is(Mode::MODE_TARGET_PAN) && mode.Is(Mode::MODE_PAN)); if (inpanmode) { if (DerivedDrawInfo.TerrainValid) { double alt= ALTITUDEMODIFY*RasterTerrain::GetTerrainHeight(GetPanLatitude(), GetPanLongitude()); if (alt==TERRAIN_INVALID) alt=0.0; _stprintf(Scale2, _T(" %.0f%s "),alt, Units::GetUnitName(Units::GetUserAltitudeUnit())); } double pandistance, panbearing; if(ValidTaskPoint(PanTaskEdit)) { _stprintf(Scale, _T("Task %.1f%s"), CALCULATED_INFO.TaskDistanceToGo*DISTANCEMODIFY, Units::GetDistanceName()/*, panbearing,_T(DEG)*/ ); } else { DistanceBearing(DrawInfo.Latitude,DrawInfo.Longitude,GetPanLatitude(),GetPanLongitude(),&pandistance,&panbearing); _stprintf(Scale, _T(" %.1f%s %.0f%s "), pandistance*DISTANCEMODIFY, Units::GetDistanceName(), panbearing, gettext(_T("_@M2179_")) ); } _tcscat(Scale2,Scale); goto _skip1; } // // This stuff is not painted while panning, to save space on screen // // warn about missing terrain if (!DerivedDrawInfo.TerrainValid) { if (terrainwarning < 120) { // LKTOKEN _@M1335_ " TERRAIN?" _tcscat(Scale2, MsgToken(1335)); terrainwarning++; } else { // LKTOKEN _@M1336_ " T?" _tcscat(Scale2, MsgToken(1336)); terrainwarning=120; } } else terrainwarning=0; if (UseTotalEnergy) { _tcscat(Scale2, TEXT("[TE]")); // Total Energy indicator } if (zoom.AutoZoom()) { // LKTOKEN _@M1337_ " AZM" _tcscat(Scale2, MsgToken(1337)); } _skip1: // // Back painting stuff even in PAN mode // if (mode.AnyPan()) { // LKTOKEN _@M1338_ " PAN" _tcscat(Scale2, MsgToken(1338)); } if (DrawBottom) { switch(BottomMode) { case BM_TRM: // LKTOKEN _@M1340_ " TRM0" _tcscat(Scale2, MsgToken(1340)); break; case BM_CRU: // LKTOKEN _@M1341_ " NAV1" _tcscat(Scale2, MsgToken(1341)); break; case BM_HGH: // LKTOKEN _@M1342_ " ALT2" _tcscat(Scale2, MsgToken(1342)); break; case BM_AUX: // LKTOKEN _@M1343_ " STA3" _tcscat(Scale2, MsgToken(1343)); break; case BM_TSK: // LKTOKEN _@M1344_ " TSK4" _tcscat(Scale2, MsgToken(1344)); break; case BM_ALT: // LKTOKEN _@M1345_ " ATN5" _tcscat(Scale2, MsgToken(1345)); break; case BM_SYS: // LKTOKEN _@M1346_ " SYS6" _tcscat(Scale2, MsgToken(1346)); break; case BM_CUS2: // LKTOKEN _@M1347_ " CRU7" _tcscat(Scale2, MsgToken(1347)); break; case BM_CUS3: // LKTOKEN _@M1348_ " FIN8" _tcscat(Scale2, MsgToken(1348)); break; case BM_CUS: // LKTOKEN _@M1349_ " AUX9" _tcscat(Scale2, MsgToken(1349)); break; default: break; } } if (inpanmode) goto _skip2; if (ReplayLogger::IsEnabled()) { _stprintf(Scale,_T("%s %.0fX"), MsgToken(1350), // " REPLAY" ReplayLogger::TimeScale); _tcscat(Scale2, Scale); } if (BallastTimerActive) { // LKTOKEN _@M1351_ " BALLAST" _stprintf(TEMP,TEXT("%s %3.0fL"), MsgToken(1351), WEIGHTS[2]*BALLAST); _tcscat(Scale2, TEMP); } _skip2: _tcscpy(Scale,TEXT("")); _tcscpy(Scale1,TEXT("")); //if (SIMMODE && (!mode.Is(Mode::MODE_TARGET_PAN) && mode.Is(Mode::MODE_PAN)) ) { if (inpanmode) { TCHAR sCoordinate[32]={0}; Units::CoordinateToString(GetPanLongitude(), GetPanLatitude(), sCoordinate, array_size(sCoordinate)-1); _tcscat(Scale, sCoordinate); _tcscat(Scale, _T(" ")); } double mapScale=Units::ToSysDistance(zoom.Scale()*1.4); // 1.4 for mapscale symbol size on map screen // zoom.Scale() gives user units, but FormatUserMapScale() needs system distance units Units::FormatUserMapScale(NULL, mapScale, Scale1, sizeof(Scale1)/sizeof(Scale1[0])); _tcscat(Scale,Scale1); SIZE tsize; Surface.SetBackgroundTransparent(); const auto oldFont = Surface.SelectObject(MapScaleFont); const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); const auto oldBrush = Surface.SelectObject(LKBrush_Black); Surface.GetTextSize(Scale, _tcslen(Scale), &tsize); LKColor mapscalecolor = OverColorRef; if (OverColorRef==RGB_SBLACK) mapscalecolor=RGB_WHITE; LKWriteText(Surface, Scale, rc.right-NIBLSCALE(7)-tsize.cx, ytext, 0, WTMODE_OUTLINED, WTALIGN_LEFT, mapscalecolor, true); Surface.GetTextSize(Scale2, _tcslen(Scale2), &tsize); if (!DerivedDrawInfo.TerrainValid) { if (terrainwarning>0 && terrainwarning<120) mapscalecolor=RGB_RED; } LKWriteText(Surface, Scale2, rc.right-NIBLSCALE(7)-tsize.cx, ytext+tsize.cy, 0, WTMODE_OUTLINED, WTALIGN_LEFT, mapscalecolor, true); Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); Surface.SelectObject(oldFont); }
/***************************************************************** * Alpha Lima splitted RenderContest from Render Task for CC * adding FAI Sector display ****************************************************************/ void Statistics::RenderFAIOptimizer(LKSurface& Surface, const RECT& rc) { unsigned int ui; double fXY_Scale = 1.0; double lat0 = 0; double lon0 = 0; double lat1 = 0; double lon1 = 0; double lat2 = 0; double lon2 = 0; double x0, y0, x1, y1, x2=0, y2=0; double lat_c, lon_c; double lat_p = GPS_INFO.Latitude; double lon_p = GPS_INFO.Longitude; BOOL bFlat = false; #define DRAWPERCENT #ifdef DRAWPERCENT double fTotalPercent = 1.0; #endif ResetScale(); CContestMgr::CResult result = CContestMgr::Instance().Result(contestType, true); const CPointGPSArray &points = result.PointArray(); if(contestType == CContestMgr::TYPE_FAI_TRIANGLE) fXY_Scale = 1.5; // find center double fTotalDistance = result.Distance(); if (fTotalDistance < 1) fTotalDistance =1; CPointGPSArray trace; CContestMgr::Instance().Trace(trace); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); } const auto hfOldU = Surface.SelectObject(LK8PanelUnitFont); BOOL bFAITri = CContestMgr::Instance().FAI(); double fDist, fAngle; lat_c = (y_max+y_min)/2; lon_c = (x_max+x_min)/2; double xp = (lon_p-lon_c)*fastcosine(lat_p); double yp = (lat_p-lat_c); // find scale ResetScale(); lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); for(ui=0; ui<trace.size(); ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); } ScaleMakeSquare(rc); if(result.Type() == contestType) { for(ui=0; ui<points.size()-1; ui++) { lat1 = points[ui].Latitude(); lon1 = points[ui].Longitude(); lat2 = points[ui+1].Latitude(); lon2 = points[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DistanceBearing(lat1, lon1, lat2, lon2, &fDist, &fAngle); if( (ui <points.size()-2) && !bFlat && ((fDist / fTotalDistance ) > 0.05) ) { if(fDist > 5000) { #ifndef UNDITHER LKColor rgbCol = RGB_BLUE; switch(ui) { case 0: rgbCol = RGB_LIGHTYELLOW; break; case 1: rgbCol = RGB_LIGHTCYAN ; break; case 2: rgbCol = RGB_LIGHTGREEN ; break; default: break; } #else LKColor rgbCol = RGB_DARKBLUE; switch(ui) { case 0: rgbCol = RGB_LIGHTGREY; break; case 1: rgbCol = RGB_GREY ; break; case 2: rgbCol = RGB_MIDDLEGREY ; break; default: break; } #endif RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, rgbCol ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, rgbCol ); } } if((fDist / fTotalDistance ) > 0.45) /* prevent drawing almost same sectors */ bFlat = true; } // draw track for(ui=0; trace.size() && ui<trace.size()-1; ui++) { lat1 = trace[ui].Latitude(); lon1 = trace[ui].Longitude(); lat2 = trace[ui+1].Latitude(); lon2 = trace[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_MEDIUMBLACK); } for(ui=0; ui<points.size()-1; ui++) { lat1 = points[ui].Latitude(); lon1 = points[ui].Longitude(); lat2 = points[ui+1].Latitude(); lon2 = points[ui+1].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); int style = STYLE_REDTHICK; if((ui > 0) && (ui < 3)) { style = STYLE_BLUETHIN; DistanceBearing(lat1, lon1, lat2, lon2, &fDist, &fAngle); #ifdef DRAWPERCENT if((result.Distance()> 5000) && bFAITri) { TCHAR text[180]; SIZE tsize; fTotalPercent -= fDist/result.Distance(); _stprintf(text, TEXT("%3.1f%%"), (fDist/result.Distance()*100.0)); Surface.GetTextSize(text, _tcslen(text), &tsize); #ifndef UNDITHER Surface.SetTextColor(RGB_BLUE); #else Surface.SetTextColor(RGB_BLACK); #endif Surface.DrawText(ScaleX(rc, x1 +( x2-x1)/2)-tsize.cx/2, ScaleY(rc,y1 + (y2-y1)/2), text, _tcslen(text)); } #endif DrawLine(Surface, rc, x1, y1, x2, y2, style); } } if(bFAITri) { if(points.size() >3) { if(ISPARAGLIDER) { lat0 = CContestMgr::Instance().GetBestNearClosingPoint().Latitude(); lon0 = CContestMgr::Instance().GetBestNearClosingPoint().Longitude(); lat1 = CContestMgr::Instance().GetBestClosingPoint().Latitude(); lon1 = CContestMgr::Instance().GetBestClosingPoint().Longitude(); x1 = (lon0-lon_c)*fastcosine(lat0); y1 = (lat0-lat_c); x2 = (lon1-lon_c)*fastcosine(lat1); y2 = (lat1-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_ORANGETHIN ); //result.Predicted() ? STYLE_BLUETHIN : STYLE_REDTHICK); } lat1 = points[1].Latitude(); lon1 = points[1].Longitude(); lat2 = points[3].Latitude(); lon2 = points[3].Longitude(); x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_THINDASHPAPER ); //result.Predicted() ? STYLE_BLUETHIN : STYLE_REDTHICK); #ifdef DRAWPERCENT TCHAR text[180]; SIZE tsize; _stprintf(text, TEXT("%3.1f%%"), (fTotalPercent*100.0)); Surface.GetTextSize(text, _tcslen(text), &tsize); #ifndef UNDITHER Surface.SetTextColor(RGB_LIGHTBLUE); #else Surface.SetTextColor(RGB_RED); #endif Surface.DrawText(ScaleX(rc, x1 +( x2-x1)/2)-tsize.cx/2, ScaleY(rc,y1 + (y2-y1)/2), text, _tcslen(text)); #endif lat0 = CContestMgr::Instance().GetClosingPoint().Latitude(); lon0 = CContestMgr::Instance().GetClosingPoint().Longitude(); x0 = (lon0-lon_c)*fastcosine(lat0); y0 = (lat0-lat_c); DrawLine(Surface, rc, xp, yp, x0, y0, STYLE_REDTHICK); } } } DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); Surface.SetBackgroundTransparent(); #ifndef UNDITHER Surface.SetTextColor(RGB_MAGENTA); #else Surface.SetTextColor(RGB_BLACK); #endif DrawLabel(Surface, rc, TEXT("O"), xp, yp); Surface.SelectObject(hfOldU); }
void MapWindow::RenderNearAirspace(LKSurface& Surface, const RECT rci) { RECT rc = rci; /* rectangle for sideview */ RECT rct = rc; /* rectangle for topview */ rc.top = (int)((double)(rci.bottom-rci.top )*fSplitFact); rct.bottom = rc.top ; // Expose the topview rect size in use.. Current_Multimap_TopRect=rct; LKFont hfOldFnt = Surface.SelectObject(LK8PanelUnitFont/* Sender->GetFont()*/); int *iSplit = &Multimap_SizeY[Get_Current_Multimap_Type()]; int k; static double fHeigtScaleFact = 1.0; double GPSlat, GPSlon, GPSalt, GPSbrg; double calc_terrainalt; double calc_altitudeagl; // double alt; TCHAR text[TBSIZE+1]; TCHAR buffer[TBSIZE+1]; CAirspaceBase near_airspace; CAirspace *found = NULL; // bool bFound = false; DiagrammStruct sDia; bool bAS_Inside=false; int iAS_Bearing=0; int iAS_HorDistance=15000; int iABS_AS_HorDistance=0; int iAS_VertDistance=0; bool bValid; static bool bHeightScale = false; long wpt_brg = 0; POINT line[2]; POINT TxYPt; POINT TxXPt; SIZE tsize; LKColor GREEN_COL = RGB_GREEN; LKColor BLUE_COL = RGB_BLUE; LKColor LIGHTBLUE_COL = RGB_LIGHTBLUE; BOOL bInvCol = true; //INVERTCOLORS unsigned short getsideviewpage=GetSideviewPage(); LKASSERT(getsideviewpage<3); if(bInvCol) Sideview_TextColor = INV_GROUND_TEXT_COLOUR; else Sideview_TextColor = RGB_WHITE; switch(LKevent) { case LKEVENT_NEWRUN: // CALLED ON ENTRY: when we select this page coming from another mapspace bHeightScale = false; // fZOOMScale[getsideviewpage] = 1.0; fHeigtScaleFact = 1.0; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_UP: // click on upper part of screen, excluding center if(bHeightScale) fHeigtScaleFact /= ZOOMFACTOR; else fZOOMScale[getsideviewpage] /= ZOOMFACTOR; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_DOWN: // click on lower part of screen, excluding center if(bHeightScale) fHeigtScaleFact *= ZOOMFACTOR; else fZOOMScale[getsideviewpage] *= ZOOMFACTOR; if (IsMultimapTopology()) ForceVisibilityScan=true; break; case LKEVENT_LONGCLICK: for (k=0 ; k <= Sideview_iNoHandeldSpaces; k++) { if( Sideview_pHandeled[k].psAS != NULL) { if (PtInRect(&(Sideview_pHandeled[k].rc), startScreen)) { #if 1 // MULTISELECT dlgAddMultiSelectListItem((long*) Sideview_pHandeled[k].psAS, 0, IM_AIRSPACE, 0); #else if (EnableSoundModes)PlayResource(TEXT("IDR_WAV_BTONE4")); dlgAirspaceDetails(Sideview_pHandeled[k].psAS); // dlgA #endif LKevent=LKEVENT_NONE; } } } dlgMultiSelectListShowModal(); if ( LKevent != LKEVENT_NONE ) { if (PtInRect(&rc, startScreen)) bHeightScale = !bHeightScale; if (PtInRect(&rct, startScreen)) bHeightScale = false; } break; case LKEVENT_PAGEUP: #ifdef OFFSET_SETP if(bHeightScale) fOffset -= OFFSET_SETP; else #endif { if(*iSplit == SIZE1) *iSplit = SIZE0; if(*iSplit == SIZE2) *iSplit = SIZE1; if(*iSplit == SIZE3) *iSplit = SIZE2; } break; case LKEVENT_PAGEDOWN: #ifdef OFFSET_SETP if(bHeightScale) fOffset += OFFSET_SETP; else #endif { if(*iSplit == SIZE2) *iSplit = SIZE3; if(*iSplit == SIZE1) *iSplit = SIZE2; if(*iSplit == SIZE0) *iSplit = SIZE1; } break; } LKASSERT(((*iSplit==SIZE0)||(*iSplit==SIZE1)||(*iSplit==SIZE2)||(*iSplit==SIZE3)||(*iSplit==SIZE4))); LKevent=LKEVENT_NONE; // Current_Multimap_SizeY is global, and must be used by all multimaps! // It is defined in Multimap.cpp and as an external in Multimap.h // It is important that it is updated, because we should resize terrain // only if needed! Resizing terrain takes some cpu and some time. // So we need to know when this is not necessary, having the same size of previous // multimap, if we are switching. // The current implementation is terribly wrong by managing resizing of sideview in // each multimap: it should be done by a common layer. // CAREFUL: // If for any reason DrawTerrain() is called after resizing to 0 (full sideview) // LK WILL CRASH with no hope to recover. if(Current_Multimap_SizeY != *iSplit) { Current_Multimap_SizeY=*iSplit; SetSplitScreenSize(*iSplit); rc.top = (long)((double)(rci.bottom-rci.top )*fSplitFact); rct.bottom = rc.top ; } if(bInvCol) { GREEN_COL = GREEN_COL.ChangeBrightness(0.6); BLUE_COL = BLUE_COL.ChangeBrightness(0.6);; LIGHTBLUE_COL = LIGHTBLUE_COL.ChangeBrightness(0.4);; } GPSlat = DrawInfo.Latitude; GPSlon = DrawInfo.Longitude; GPSalt = DrawInfo.Altitude; GPSbrg = DrawInfo.TrackBearing; calc_terrainalt = DerivedDrawInfo.TerrainAlt; calc_altitudeagl = DerivedDrawInfo.AltitudeAGL; GPSalt = DerivedDrawInfo.NavAltitude; bValid = false; iAS_HorDistance = 5000; iAS_Bearing = (int)GPSbrg; iAS_VertDistance= 0; found = CAirspaceManager::Instance().GetNearestAirspaceForSideview(); if(found != NULL) { near_airspace = CAirspaceManager::Instance().GetAirspaceCopy(found); bValid = near_airspace.GetDistanceInfo(bAS_Inside, iAS_HorDistance, iAS_Bearing, iAS_VertDistance); } iABS_AS_HorDistance = abs( iAS_HorDistance); wpt_brg = (long)AngleLimit360(GPSbrg - iAS_Bearing + 90.0); // Variables from ASP system here contain the following informations: // fAS_HorDistance - always contains horizontal distance from the asp, negative if horizontally inside (This does not mean that we're inside vertically as well!) // fAS_Bearing - always contains bearing to the nearest horizontal point // bValid - true if bAS_Inside, iAS_HorDistance, iAS_Bearing, iAS_VertDistance contains valid informations // this will be true if the asp border is close enough to be tracked by the warning system // bAS_Inside - current position is inside in the asp, calculated by the warning system // iAS_HorDistance - horizontal distance to the nearest horizontal border, negative if horizontally inside, calculated by the warning system // iAS_Bearing - bearing to the nearest horizontal border, calculated by the warning system // iAS_VertDistance - vertical distance to the nearest asp border, negative if the border is above us, positive if the border below us, calculated by the warning system // near_airspace.WarningLevel(): // awNone - no warning condition exists // awYellow - current position is near to a warning position // awRed - current posisiton is forbidden by asp system, we are in a warning position /********************************************************************* * calc the horizontal zoom *********************************************************************/ sDia.fXMin = -5000.0; sDia.fXMax = 5000.0; /* even when invalid the horizontal distance is calculated correctly */ if(bValid) { double fScaleDist = iABS_AS_HorDistance; sDia.fXMin = min(-2500.0 , fScaleDist * 1.5 ); sDia.fXMax = max( 2500.0 , fScaleDist * 1.5 ); #ifdef NEAR_AS_ZOOM_1000M if(((iABS_AS_HorDistance) < 900) && (bValid)) // 1km zoom { sDia.fXMin = min(-900.0, fScaleDist * 1.5 ); sDia.fXMax = max( 900.0, fScaleDist * 1.5 ); } #endif #ifdef NEAR_AS_ZOOM_1000FT if((abs(iABS_AS_HorDistance) < 333)) // 1000ft zoom { sDia.fXMin = min(-333.0, fScaleDist * 1.5 ); sDia.fXMax = max( 333.0, fScaleDist * 1.5 ); } #endif } #define RND_FACT 10.0 if( ( sDia.fXMax *fZOOMScale[getsideviewpage]) > 100000) fZOOMScale[getsideviewpage] /= ZOOMFACTOR; if(( sDia.fXMax *fZOOMScale[getsideviewpage]) < 500) { fZOOMScale[getsideviewpage] *= ZOOMFACTOR; } double fOldZoomScale=-1; if(fZOOMScale[getsideviewpage] != fOldZoomScale) { fOldZoomScale = fZOOMScale[getsideviewpage]; sDia.fXMax = sDia.fXMax *fZOOMScale[getsideviewpage]; sDia.fXMin = -sDia.fXMax /5; } /********************************************************************* * calc the vertical zoom *********************************************************************/ sDia.fYMin = max(0.0, GPSalt-2300); sDia.fYMax = max(MAXALTTODAY, GPSalt+1000); if(bValid) { double fBottom = near_airspace.Base()->Altitude; sDia.fYMin = min(fBottom*0.8, sDia.fYMin ); sDia.fYMin = max(0.0, sDia.fYMin ); if(sDia.fYMin < 300) sDia.fYMin =0; sDia.fYMax = max((fBottom*1.2f), sDia.fYMax ); if(abs(iAS_VertDistance) < 250) { sDia.fYMax = ((int)((GPSalt+abs(iAS_VertDistance))/400) + 2) *400 ; sDia.fYMin = ((int)((GPSalt-abs(iAS_VertDistance))/400) - 1) *400 ; if(sDia.fYMin-MIN_ALTITUDE < 0) sDia.fYMin = 0; } #ifdef VERTICAL_ZOOM_50 if(abs(iAS_VertDistance) < 50) { sDia.fYMax = ((int)((GPSalt+abs(iAS_VertDistance))/100) + 2) *100 ; sDia.fYMin = ((int)((GPSalt-abs(iAS_VertDistance))/100) - 1) *100 ; if(sDia.fYMin-MIN_ALTITUDE < 0) sDia.fYMin = 0; } #endif sDia.fYMin = max((double)0.0f,(double) sDia.fYMin); #ifdef OFFSET_SETP if(( sDia.fYMax + fOffset) > MAX_ALTITUDE) fOffset -= OFFSET_SETP; if(( sDia.fYMin + fOffset) < 0.0) fOffset += OFFSET_SETP; sDia.fYMin += fOffset; sDia.fYMax += fOffset; #endif // if(fHeigtScaleFact * sDia.fYMax > MAX_ALTITUDE ) // fHeigtScaleFact /=ZOOMFACTOR; if(fHeigtScaleFact * sDia.fYMax < MIN_ALTITUDE ) fHeigtScaleFact *=ZOOMFACTOR; sDia.fYMax *= fHeigtScaleFact; } /**************************************************************************************************** * draw topview first ****************************************************************************************************/ if(fSplitFact > 0.0) { sDia.rc = rct; sDia.rc.bottom-=1; SharedTopView(Surface, &sDia, (double) iAS_Bearing, (double) wpt_brg); } /**************************************************************************************************** * draw airspace and terrain elements ****************************************************************************************************/ RECT rcc = rc; /* rc corrected */ if(sDia.fYMin < GC_SEA_LEVEL_TOLERANCE) rcc.bottom -= SV_BORDER_Y; /* scale witout sea */ sDia.rc = rcc; RenderAirspaceTerrain(Surface, GPSlat, GPSlon, iAS_Bearing, &sDia ); LKFont hfOld = Surface.SelectObject(LK8InfoNormalFont); if(bValid) { LKASSERT(_tcslen(near_airspace.Name())<TBSIZE); // Diagnostic only in 3.1j, to be REMOVED LK_tcsncpy(Sideview_szNearAS, near_airspace.Name(), TBSIZE ); } else { _stprintf(text,TEXT("%s"), MsgToken(1259)); // LKTOKEN _@M1259_ "Too far, not calculated" Surface.GetTextSize(text, _tcslen(text), &tsize); TxYPt.x = (rc.right-rc.left-tsize.cx)/2; TxYPt.y = (rc.bottom-rc.top)/2; Surface.SetBkMode(TRANSPARENT); Surface.DrawText(TxYPt.x, TxYPt.y-20, text, _tcslen(text)); _stprintf(Sideview_szNearAS,TEXT("%s"), text); } Surface.SelectObject(hfOld); /**************************************************************************************************** * draw airspace and terrain elements ****************************************************************************************************/ /**************************************************************************************************** * draw diagram ****************************************************************************************************/ double xtick = 1.0; double fRange =fabs(sDia.fXMax - sDia.fXMin) ; if (fRange>3.0*1000.0) xtick = 2.0; if (fRange>15*1000.0) xtick = 5.0; if (fRange>50.0*1000.0) xtick = 10.0; if (fRange>100.0*1000.0) xtick = 20.0; if (fRange>200.0*1000.0) xtick = 25.0; if (fRange>250.0*1000.0) xtick = 50.0; if (fRange>500.0*1000.0) xtick = 100.0; if (fRange>1000.0*1000.0) xtick = 1000.0; if(bInvCol) { Surface.SelectObject(LK_BLACK_PEN); Surface.SelectObject(LKBrush_Black); } else { Surface.SelectObject(LK_WHITE_PEN); Surface.SelectObject(LKBrush_White); } LKColor txtCol = GROUND_TEXT_COLOUR; if(bInvCol) if(sDia.fYMin > GC_SEA_LEVEL_TOLERANCE) txtCol = INV_GROUND_TEXT_COLOUR; Surface.SetBkMode(TRANSPARENT); Surface.SetTextColor(txtCol); _stprintf(text, TEXT("%s"),Units::GetUnitName(Units::GetUserDistanceUnit())); switch(GetMMNorthUp(getsideviewpage)) { case NORTHUP: default: DrawXGrid(Surface, rc , xtick/DISTANCEMODIFY, xtick, 0,TEXT_ABOVE_LEFT, RGB_BLACK, &sDia,text); break; case TRACKUP: DrawXGrid(Surface, rci, xtick/DISTANCEMODIFY, xtick, 0,TEXT_ABOVE_LEFT, RGB_BLACK, &sDia,text); break; } Surface.SetTextColor(Sideview_TextColor); double fHeight = (sDia.fYMax-sDia.fYMin); double ytick = 100.0; if (fHeight >500.0) ytick = 200.0; if (fHeight >1000.0) ytick = 500.0; if (fHeight >2000.0) ytick = 1000.0; if (fHeight >4000.0) ytick = 2000.0; if (fHeight >8000.0) ytick = 4000.0; if(Units::GetUserAltitudeUnit() == unFeet) ytick = ytick * FEET_FACTOR; _stprintf(text, TEXT("%s"),Units::GetUnitName(Units::GetUserAltitudeUnit())); if(sDia.fYMin < GC_SEA_LEVEL_TOLERANCE) rc.bottom -= SV_BORDER_Y; /* scale witout sea */ DrawYGrid(Surface, rc, ytick/ALTITUDEMODIFY,ytick, 0,TEXT_UNDER_RIGHT ,Sideview_TextColor, &sDia, text); if(!bInvCol) Surface.SetBkMode(OPAQUE); /**************************************************************************************************** * draw AGL ****************************************************************************************************/ if(calc_altitudeagl - sDia.fYMin > 500) { Surface.SetTextColor(LIGHTBLUE_COL); Units::FormatUserAltitude(calc_altitudeagl, buffer, 7); LK_tcsncpy(text, MsgToken(1742), TBSIZE-_tcslen(buffer)); // AGL: _tcscat(text,buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); TxYPt.x = CalcDistanceCoordinat(0, &sDia)- tsize.cx/2; TxYPt.y = CalcHeightCoordinat( (calc_terrainalt + calc_altitudeagl )*0.8, &sDia ); if((tsize.cy) < ( CalcHeightCoordinat( calc_terrainalt, &sDia )- TxYPt.y )) { Surface.DrawText(TxYPt.x+IBLSCALE(1), TxYPt.y , text, _tcslen(text)); } } Surface.SetBkMode(TRANSPARENT); /**************************************************************************************************** * Print current Elevation ****************************************************************************************************/ Surface.SetTextColor(RGB_BLACK); int x,y; if((calc_terrainalt- sDia.fYMin) > 0) { Units::FormatUserAltitude(calc_terrainalt, buffer, 7); LK_tcsncpy(text, MsgToken(1743), TBSIZE-_tcslen(buffer)); // ELV: _tcscat(text,buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); x = CalcDistanceCoordinat(0, &sDia) - tsize.cx/2; y = CalcHeightCoordinat( calc_terrainalt, &sDia ); if ((ELV_FACT*tsize.cy) < abs(rc.bottom - y)) { Surface.DrawText(x, rc.bottom -(int)(ELV_FACT * tsize.cy), text, _tcslen(text)); } } /**************************************************************************************************** * draw side elements ****************************************************************************************************/ Surface.SetTextColor(Sideview_TextColor); Surface.SetBkMode(OPAQUE); LKFont hfOld2 = Surface.SelectObject(LK8InfoNormalFont); // DrawTelescope ( hdc, iAS_Bearing-90.0, rc.right - NIBLSCALE(13), rc.top + NIBLSCALE(58)); Surface.SelectObject(hfOld2); Surface.SetBkMode(TRANSPARENT); Surface.SelectObject(hfOld); Surface.SetTextColor(GROUND_TEXT_COLOUR); if(bInvCol) if(sDia.fYMin > GC_SEA_LEVEL_TOLERANCE) Surface.SetTextColor(INV_GROUND_TEXT_COLOUR); /****************************************************************************************************/ /****************************************************************************************************/ /**************************************************************************************************** * draw distances to next airspace ****************************************************************************************************/ /****************************************************************************************************/ /****************************************************************************************************/ if (bValid) { /**************************************************************************************************** * draw horizontal distance to next airspace ****************************************************************************************************/ Surface.SetTextColor(Sideview_TextColor); Surface.SetBkMode(OPAQUE); LKFont hfOldU = Surface.SelectObject(LK8InfoNormalFont); // horizontal distance line[0].x = CalcDistanceCoordinat(0, &sDia); line[0].y = CalcHeightCoordinat( GPSalt, &sDia ); line[1].x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia); line[1].y = line[0].y; Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); if(iAS_HorDistance < 0) { line[0].y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance, &sDia ); line[1].y = line[0].y; Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); } bool bLeft = false; if( line[0].x < line[1].x) bLeft = false; else bLeft = true; Units::FormatUserDistance(iABS_AS_HorDistance, buffer, 7); _stprintf(text,_T(" %s"),buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); if((GPSalt- sDia.fYMin /*-calc_terrainalt */) < 300) TxXPt.y = CalcHeightCoordinat( GPSalt, &sDia ) - tsize.cy; else TxXPt.y = CalcHeightCoordinat( GPSalt, &sDia ) + NIBLSCALE(3); if(tsize.cx > (line[1].x - line[0].x) ) TxXPt.x = CalcDistanceCoordinat( iABS_AS_HorDistance ,&sDia) -tsize.cx- NIBLSCALE(3); else TxXPt.x = CalcDistanceCoordinat( iABS_AS_HorDistance / 2.0, &sDia) -tsize.cx/2; Surface.DrawText(TxXPt.x, TxXPt.y, text, _tcslen(text)); /**************************************************************************************************** * draw vertical distance to next airspace ****************************************************************************************************/ line[0].x = CalcDistanceCoordinat( iABS_AS_HorDistance , &sDia); line[0].y = CalcHeightCoordinat( GPSalt, &sDia ); line[1].x = line[0].x; line[1].y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance, &sDia ); Surface.DrawDashLine(THICK_LINE, line[0], line[1], Sideview_TextColor, rc); Units::FormatUserAltitude( (double)abs(iAS_VertDistance), buffer, 7); _stprintf(text,_T(" %s"),buffer); Surface.GetTextSize(text, _tcslen(text), &tsize); if ( bLeft ) TxYPt.x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia)- tsize.cx - NIBLSCALE(3); else TxYPt.x = CalcDistanceCoordinat(iABS_AS_HorDistance, &sDia)+ NIBLSCALE(5); if( abs( line[0].y - line[1].y) > tsize.cy) TxYPt.y = CalcHeightCoordinat( GPSalt - (double)iAS_VertDistance/2.0, &sDia) -tsize.cy/2 ; else TxYPt.y = min( line[0].y , line[1].y) - tsize.cy ; Surface.DrawText(TxYPt.x, TxYPt.y , text, _tcslen(text)); Surface.SelectObject(hfOldU); } /**************************************************************************************************** * draw plane sideview at least ****************************************************************************************************/ RenderPlaneSideview(Surface, 0.0 , GPSalt,wpt_brg, &sDia ); hfOldFnt = Surface.SelectObject(LK8InfoNormalFont/* Sender->GetFont()*/); DrawMultimap_SideTopSeparator(Surface,rct); /**************************************************************************************************** * draw selection frame ****************************************************************************************************/ if(bHeightScale) DrawSelectionFrame(Surface, rc); #ifdef TOP_SELECTION_FRAME else DrawSelectionFrame(hdc, rci); #endif Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/); Surface.SetBkMode(TRANSPARENT); Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/); }
void MapWindow::DrawAspNearest(LKSurface& Surface, const RECT& rc) { SIZE ASPTextSize, DSTextSize, BETextSize, TYTextSize, ACTextSize, HLTextSize, MITextSize; SIZE phdrTextSize; TCHAR Buffer[LKSIZEBUFFERLARGE]; static RECT s_sortBox[6]; static TCHAR Buffer1[MAXNEARAIRSPACES][MAXAIRSPACENUMPAGES][30], Buffer2[MAXNEARAIRSPACES][MAXAIRSPACENUMPAGES][12]; static TCHAR Buffer3[MAXNEARAIRSPACES][MAXAIRSPACENUMPAGES][12]; static TCHAR Buffer4[MAXNEARAIRSPACES][MAXAIRSPACENUMPAGES][12], Buffer5[MAXNEARAIRSPACES][MAXAIRSPACENUMPAGES][12]; static short s_maxnlname; static TCHAR s_trailspace[3]; short i, j, k, iRaw, wlen, rli=0, curpage, drawn_items_onpage; double value; LKColor rcolor; // column0 starts after writing 1:2 (ModeIndex:CURTYPE+1) with a different font.. static short Column0; static short Column1, Column2, Column3, Column4, Column5; static POINT p1, p2; static short s_rawspace; static unsigned short lincr; // Printable area for live nearest values static short left,right,bottom; // one for each mapspace, no matter if 0 and 1 are unused // we lock to current mapspace for this drawing short curmapspace=MapSpaceMode; static int AspNumraws=0; static bool usetwolines=0; // Vertical and horizontal spaces #define INTERRAW 1 #define HEADRAW NIBLSCALE(6) BrushReference sortbrush; RECT invsel; if (INVERTCOLORS) { sortbrush=LKBrush_LightGreen; } else { sortbrush=LKBrush_DarkGreen; } if (DoInit[MDI_DRAWASPNEAREST]) { usetwolines=UseTwoLines; // Set screen borders to avoid writing on extreme pixels if ( !ScreenLandscape ) { // Portrait mode can work on two rows left=rc.left+NIBLSCALE(1); right=rc.right-NIBLSCALE(1); bottom=rc.bottom-BottomSize-NIBLSCALE(2); s_maxnlname=7; _stprintf(Buffer,TEXT("AKSJSMMMM")); } else { left=rc.left+NIBLSCALE(5); right=rc.right-NIBLSCALE(5); bottom=rc.bottom-BottomSize; s_maxnlname=15; _stprintf(Buffer,TEXT("ABCDEF GHIJK-LM")); // now resize for tuning on resolutions if (ScreenSize == ss320x240) s_maxnlname=9; if (ScreenSize == ss400x240) s_maxnlname=10; } Buffer[s_maxnlname]='\0'; /// WPT is now AIRSPACE name Surface.SelectObject(LK8InfoBigFont); // Text font for Nearest was LK8Title Surface.GetTextSize(Buffer, _tcslen(Buffer), &ASPTextSize); // DST is always distance _stprintf(Buffer,TEXT("000.0")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &DSTextSize); // Bearing _stprintf(Buffer,TEXT("<<123")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &BETextSize); // TYPE, 4 letters printed #define LKASP_TYPE_LEN 4 _stprintf(Buffer,TEXT("CTRA")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &TYTextSize); // Flags can be SFE, three chars _stprintf(Buffer,TEXT("SFE")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &ACTextSize); Surface.SelectObject(LK8InfoNormalFont); _stprintf(Buffer,TEXT("MMMM")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &HLTextSize); Surface.SelectObject(LK8PanelMediumFont); _stprintf(Buffer,TEXT("1.1")); Surface.GetTextSize(Buffer, _tcslen(Buffer), &MITextSize); short afterwpname=left+ASPTextSize.cx+NIBLSCALE(5); short intercolumn=(right-afterwpname- DSTextSize.cx-BETextSize.cx-TYTextSize.cx-ACTextSize.cx)/3; // Col0 is where ASP 1/3 can be written, after ModeIndex:Curtype Column0=MITextSize.cx+LEFTLIMITER+NIBLSCALE(5); Column1=left; // WP align left if (ScreenLandscape || !usetwolines) { Column2=afterwpname+TYTextSize.cx; // TY align right Column3=Column2+intercolumn+DSTextSize.cx; // DS align right Column4=Column3+intercolumn+BETextSize.cx; // BE align right Column5=Column4+intercolumn+ACTextSize.cx; // AC align right } else { Surface.SelectObject(LK8PanelMediumFont); Surface.GetTextSize(_T("2.4_ASP_3/3_"), 12, &phdrTextSize); int s=(rc.right - phdrTextSize.cx)/4; Column5= right - NIBLSCALE(2); Column4= Column5 - s; Column3= Column4 - s; Column2= Column3 - s; } if ( !ScreenLandscape ) { if (usetwolines) { lincr=2; TopSize=rc.top+HEADRAW*2+ASPTextSize.cy; } else { lincr=1; TopSize=rc.top+HEADRAW*2+HLTextSize.cy; } p1.x=0; p1.y=TopSize; p2.x=rc.right; p2.y=p1.y; TopSize+=HEADRAW; AspNumraws=(bottom - TopSize) / (ASPTextSize.cy+(INTERRAW*2)); if (AspNumraws>MAXNEARAIRSPACES) AspNumraws=MAXNEARAIRSPACES; s_rawspace=(ASPTextSize.cy+INTERRAW); Column5=rc.right-NIBLSCALE(1)-1; _tcscpy(s_trailspace,_T("")); } else { lincr=1; TopSize=rc.top+HEADRAW*2+HLTextSize.cy; p1.x=0; p1.y=TopSize; p2.x=rc.right; p2.y=p1.y; TopSize+=HEADRAW/2; AspNumraws=(bottom - TopSize) / (ASPTextSize.cy+INTERRAW); if (AspNumraws>MAXNEARAIRSPACES) AspNumraws=MAXNEARAIRSPACES; s_rawspace=(ASPTextSize.cy+INTERRAW); _tcscpy(s_trailspace,_T(" ")); } #define INTERBOX intercolumn/2 s_sortBox[0].left=Column0; if (!ScreenLandscape && usetwolines) { s_sortBox[0].right=phdrTextSize.cx; } else { if ( !ScreenLandscape ) s_sortBox[0].right= left+ASPTextSize.cx-NIBLSCALE(2); else s_sortBox[0].right=left+ASPTextSize.cx-NIBLSCALE(10); } s_sortBox[0].top=2; s_sortBox[0].bottom=p1.y; SortBoxX[MSM_AIRSPACES][0]=s_sortBox[0].right; if (!ScreenLandscape && usetwolines) { s_sortBox[1].left=s_sortBox[0].right; } else { if ( !ScreenLandscape ) s_sortBox[1].left=Column1+afterwpname-INTERBOX; else s_sortBox[1].left=Column1+afterwpname-INTERBOX-NIBLSCALE(2); } if (!ScreenLandscape && usetwolines) s_sortBox[1].right=Column2+NIBLSCALE(2); else s_sortBox[1].right=Column2+INTERBOX; s_sortBox[1].top=2; s_sortBox[1].bottom=p1.y; SortBoxX[MSM_AIRSPACES][1]=s_sortBox[1].right; if (!ScreenLandscape && usetwolines) { s_sortBox[2].left=Column2+NIBLSCALE(2); s_sortBox[2].right=Column3+NIBLSCALE(2); } else { s_sortBox[2].left=Column2+INTERBOX; s_sortBox[2].right=Column3+INTERBOX; } s_sortBox[2].top=2; s_sortBox[2].bottom=p1.y; SortBoxX[MSM_AIRSPACES][2]=s_sortBox[2].right; if (!ScreenLandscape && usetwolines) { s_sortBox[3].left=Column3+NIBLSCALE(2); s_sortBox[3].right=Column4+NIBLSCALE(2); } else { s_sortBox[3].left=Column3+INTERBOX; s_sortBox[3].right=Column4+INTERBOX; } s_sortBox[3].top=2; s_sortBox[3].bottom=p1.y; SortBoxX[MSM_AIRSPACES][3]=s_sortBox[3].right; if (!ScreenLandscape && usetwolines) { s_sortBox[4].left=Column4+NIBLSCALE(2); s_sortBox[4].right=rc.right-1; } else { s_sortBox[4].left=Column4+INTERBOX; s_sortBox[4].right=rc.right-1; } s_sortBox[4].top=2; s_sortBox[4].bottom=p1.y; SortBoxX[MSM_AIRSPACES][4]=s_sortBox[4].right; SortBoxY[MSM_AIRSPACES]=p1.y; AspNumpages=roundupdivision(MAXNEARAIRSPACES*lincr, AspNumraws); if (AspNumpages>MAXAIRSPACENUMPAGES) AspNumpages=MAXAIRSPACENUMPAGES; else if (AspNumpages<1) AspNumpages=1; SelectedRaw[MSM_AIRSPACES]=0; SelectedPage[MSM_AIRSPACES]=0; DoInit[MDI_DRAWASPNEAREST]=false; return; } // doinit bool ndr; ndr=DoAirspaces(&DrawInfo, &DerivedDrawInfo); AspNumpages=roundupdivision(LKNumAirspaces*lincr, AspNumraws); if (AspNumpages>MAXAIRSPACENUMPAGES) AspNumpages=MAXAIRSPACENUMPAGES; else if (AspNumpages<1) AspNumpages=1; curpage=SelectedPage[curmapspace]; if (curpage<0||curpage>=MAXAIRSPACENUMPAGES) { // TODO also >Numpages SelectedPage[curmapspace]=0; LKevent=LKEVENT_NONE; return; } switch (LKevent) { case LKEVENT_NONE: break; case LKEVENT_ENTER: LKevent=LKEVENT_NONE; i=LKSortedAirspaces[SelectedRaw[curmapspace] + (curpage*AspNumraws/lincr)]; if ( ValidAirspace(i)) { CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef()); CAirspaceManager::Instance().PopupAirspaceDetail(LKAirspaces[i].Pointer); } LKevent=LKEVENT_NONE; return; break; case LKEVENT_DOWN: if (++SelectedRaw[curmapspace] >=AspNumraws) SelectedRaw[curmapspace]=0; break; case LKEVENT_UP: if (--SelectedRaw[curmapspace] <0) SelectedRaw[curmapspace]=AspNumraws-1; break; case LKEVENT_PAGEUP: LKevent=LKEVENT_NONE; break; case LKEVENT_PAGEDOWN: LKevent=LKEVENT_NONE; break; case LKEVENT_NEWRUN: for (i=0; i<MAXNEARAIRSPACES; i++) { for (k=0; k<MAXAIRSPACENUMPAGES; k++) { _stprintf(Buffer1[i][k], _T("----------------------------")); // max 30 Buffer1[i][k][s_maxnlname+7]='\0'; // some more dashes _stprintf(Buffer2[i][k],_T("----")); _stprintf(Buffer3[i][k],_T("----")); _stprintf(Buffer4[i][k],_T("----")); _stprintf(Buffer5[i][k],_T(" ")); } } break; case LKEVENT_NEWPAGE: break; default: LKevent=LKEVENT_NONE; break; } if (INVERTCOLORS) Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), p1, p2, RGB_GREEN, rc); else Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), p1, p2, RGB_DARKGREEN, rc); Surface.SelectObject(LK8InfoNormalFont); // Heading line short cursortbox=SortedMode[curmapspace]; if ( !ScreenLandscape ) { // portrait mode Surface.FillRect(&s_sortBox[cursortbox], sortbrush); _stprintf(Buffer,TEXT("%d.%d"),ModeIndex,CURTYPE+1); Surface.SelectObject(LK8PanelMediumFont); LKWriteText(Surface, Buffer, LEFTLIMITER, rc.top+TOPLIMITER , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); Surface.SelectObject(LK8InfoNormalFont); _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1642_")), curpage+1, AspNumpages); // ASP if (cursortbox == 0) LKWriteText(Surface, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); _tcscpy(Buffer,gettext(TEXT("_@M752_"))); // Type if (cursortbox==1) LKWriteText(Surface, Buffer, Column2, HEADRAW , 0, WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column2, HEADRAW , 0, WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); _tcscpy(Buffer,gettext(TEXT("_@M1300_"))); // Dist if (cursortbox==2) LKWriteText(Surface, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); _tcscpy(Buffer,gettext(TEXT("_@M1301_"))); // Dir if (cursortbox==3) LKWriteText(Surface, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); // Active mode _tcscpy(Buffer,TEXT("*")); if (cursortbox==4) LKWriteText(Surface, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); } else { Surface.FillRect(&s_sortBox[cursortbox], sortbrush); _stprintf(Buffer,TEXT("%d.%d"),ModeIndex,CURTYPE+1); Surface.SelectObject(LK8PanelMediumFont); LKWriteText(Surface, Buffer, LEFTLIMITER, rc.top+TOPLIMITER , 0, WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); Surface.SelectObject(LK8InfoNormalFont); _stprintf(Buffer,TEXT("%s %d/%d"), gettext(TEXT("_@M1642_")), curpage+1, AspNumpages); // ASP if (cursortbox==0) LKWriteText(Surface, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column0, HEADRAW-NIBLSCALE(1) , 0,WTMODE_NORMAL, WTALIGN_LEFT, RGB_LIGHTGREEN, false); _tcscpy(Buffer,gettext(TEXT("_@M752_"))); // Type if (cursortbox==1) LKWriteText(Surface, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column2, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); _tcscpy(Buffer,gettext(TEXT("_@M1300_"))); // Dist if (cursortbox==2) LKWriteText(Surface, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column3, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); _tcscpy(Buffer,gettext(TEXT("_@M1301_"))); // dir if (cursortbox==3) LKWriteText(Surface, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column4, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); _stprintf(Buffer,TEXT("*")); if (cursortbox==4) LKWriteText(Surface, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_BLACK, false); else LKWriteText(Surface, Buffer, Column5, HEADRAW , 0,WTMODE_NORMAL, WTALIGN_RIGHT, RGB_WHITE, false); } // landscape mode Surface.SelectObject(LK8InfoBigFont); // Text font for Nearest int *psortedindex; psortedindex=LKSortedAirspaces; for (i=0, j=0, drawn_items_onpage=0; i<AspNumraws; j++, i+=lincr) { iRaw=TopSize+(s_rawspace*i); short curraw=(curpage*AspNumraws); if (!ScreenLandscape && usetwolines) { curraw/=2; curraw+=j; } else { curraw+=i; } if (curraw>=MAXNEARAIRSPACES) break; rli=*(psortedindex+curraw); if (!ndr) { goto KeepOldValues; } if ( ValidAirspace(rli) ) { // // AIRSPACE NAME // wlen=_tcslen(LKAirspaces[rli].Name); if (!ScreenLandscape && usetwolines) { LK_tcsncpy(Buffer, LKAirspaces[rli].Name, 15); } else { if (wlen>s_maxnlname) { LK_tcsncpy(Buffer, LKAirspaces[rli].Name, s_maxnlname); } else { LK_tcsncpy(Buffer, LKAirspaces[rli].Name, wlen); } } CharUpper(Buffer); _tcscpy(Buffer1[i][curpage],Buffer); // // AIRSPACE TYPE // wlen=_tcslen(LKAirspaces[rli].Type); if (wlen>LKASP_TYPE_LEN) { LK_tcsncpy(Buffer, LKAirspaces[rli].Type, LKASP_TYPE_LEN); } else { LK_tcsncpy(Buffer, LKAirspaces[rli].Type, wlen); } CharUpper(Buffer); _tcscpy(Buffer2[i][curpage],Buffer); // // AIRSPACE DISTANCE // switch(LKAirspaces[rli].WarningLevel) { case awYellow: value=LKAirspaces[rli].Distance*DISTANCEMODIFY; if (!ScreenLandscape && usetwolines) _stprintf(Buffer3[i][curpage],TEXT("%0.1lf%s!"),value,Units::GetDistanceName()); else _stprintf(Buffer3[i][curpage],TEXT("%0.1lf!"),value); break; case awRed: _stprintf(Buffer3[i][curpage],TEXT("IN")); break; default: value=LKAirspaces[rli].Distance*DISTANCEMODIFY; if (!ScreenLandscape && usetwolines) _stprintf(Buffer3[i][curpage],TEXT("%0.1lf%s"),value,Units::GetDistanceName()); else _stprintf(Buffer3[i][curpage],TEXT("%0.1lf"),value); break; } // // AIRSPACE BEARING DIFFERENCE, OR BEARING IF CIRCLING // if (!MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING)) { value = LKAirspaces[rli].Bearing - DrawInfo.TrackBearing; if (value < -180.0) value += 360.0; else if (value > 180.0) value -= 360.0; if (value > 1) _stprintf(Buffer4[i][curpage], TEXT("%2.0f%s%s"), value, gettext(_T("_@M2179_")), gettext(_T("_@M2183_"))); else if (value < -1) _stprintf(Buffer4[i][curpage], TEXT("%s%2.0f%s"), gettext(_T("_@M2182_")), -value, gettext(_T("_@M2179_"))); else _stprintf(Buffer4[i][curpage], TEXT("%s%s"), gettext(_T("_@M2182_")), gettext(_T("_@M2183_"))); } else _stprintf(Buffer4[i][curpage], TEXT("%2.0f%s"), LKAirspaces[rli].Bearing, gettext(_T("_@M2179_"))); // // AIRSPACE FLAGS // TCHAR aspflags[5]; _stprintf(aspflags,_T("%s%s%s%s"), LKAirspaces[rli].Selected ? _T("S") : _T(""), LKAirspaces[rli].Flyzone ? _T("F") : _T(" "), LKAirspaces[rli].Enabled ? _T("E") : _T("D"), s_trailspace); if (!ScreenLandscape && usetwolines) _stprintf(Buffer5[i][curpage], TEXT("*%s"), aspflags); else _stprintf(Buffer5[i][curpage], TEXT("%s"), aspflags); } else { _stprintf(Buffer1[i][curpage], _T("----------------------------")); // max 30 Buffer1[i][curpage][s_maxnlname+7]='\0'; // some more dashes _stprintf(Buffer2[i][curpage],_T("----")); _stprintf(Buffer3[i][curpage],_T("----")); _stprintf(Buffer4[i][curpage],_T("----")); _stprintf(Buffer5[i][curpage],_T(" ")); } KeepOldValues: if ( ValidAirspace(rli) ) { drawn_items_onpage++; switch(LKAirspaces[rli].WarningLevel) { case awYellow: rcolor=RGB_LIGHTYELLOW; Surface.SelectObject(LK8InfoBigItalicFont); break; case awRed: rcolor=RGB_LIGHTRED; Surface.SelectObject(LK8InfoBigItalicFont); break; case awNone: default: rcolor=RGB_WHITE; Surface.SelectObject(LK8InfoBigFont); break; } } else { rcolor=RGB_GREY; } if (ScreenLandscape || !usetwolines) { LKWriteText(Surface, Buffer1[i][curpage], Column1, iRaw , 0, WTMODE_NORMAL, WTALIGN_LEFT, rcolor, false); LKWriteText(Surface, Buffer2[i][curpage], Column2, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(Surface, Buffer3[i][curpage], Column3, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(Surface, Buffer4[i][curpage], Column4, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(Surface, Buffer5[i][curpage], Column5, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); } else { LKWriteText(Surface, Buffer1[i][curpage], Column1, iRaw , 0, WTMODE_NORMAL, WTALIGN_LEFT, rcolor, false); LKWriteText(Surface, Buffer2[i][curpage], Column5, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); iRaw+=s_rawspace; unsigned int iCol=ScreenSizeX/3; LKWriteText(Surface, Buffer3[i][curpage], iCol, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(Surface, Buffer4[i][curpage], iCol*2, iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); LKWriteText(Surface, Buffer5[i][curpage], right-IBLSCALE(2), iRaw , 0, WTMODE_NORMAL, WTALIGN_RIGHT, rcolor, false); } } if (LKevent==LKEVENT_NEWRUN || LKevent==LKEVENT_NEWPAGE ) { LKevent=LKEVENT_NONE; return; } if (drawn_items_onpage>0) { if (SelectedRaw[curmapspace] <0 || SelectedRaw[curmapspace]>(AspNumraws-1)) { return; } if (SelectedRaw[curmapspace] >= drawn_items_onpage) { if (LKevent==LKEVENT_DOWN) SelectedRaw[curmapspace]=0; else if (LKevent==LKEVENT_UP) SelectedRaw[curmapspace]=drawn_items_onpage-1; else { // DoStatusMessage(_T("Cant find valid raw")); not needed anymore SelectedRaw[curmapspace]=0; } } invsel.left=left; invsel.right=right; if (!ScreenLandscape && usetwolines) invsel.top=TopSize+(s_rawspace*SelectedRaw[curmapspace]*lincr); else invsel.top=TopSize+(s_rawspace*SelectedRaw[curmapspace])+NIBLSCALE(2); invsel.bottom=TopSize+(s_rawspace*(SelectedRaw[curmapspace]*lincr+1))-NIBLSCALE(1); if (!ScreenLandscape && usetwolines) invsel.bottom+=s_rawspace; Surface.InvertRect(invsel); } LKevent=LKEVENT_NONE; return; }
int RenderFAISector (LKSurface& Surface, const RECT& rc , double lat1, double lon1, double lat2, double lon2, int iOpposite , const LKColor& fillcolor) { POINT Pt1; float fFAI_Percentage = FAI_NORMAL_PERCENTAGE; double fDist_a, fDist_b, fDist_c, fAngle; int i; int iPolyPtr=0; double lat_d,lon_d; double alpha, fDistTri, cos_alpha=0; POINT apSectorPolygon[MAX_FAI_SECTOR_PTS+1]; DistanceBearing(lat1, lon1, lat2, lon2, &fDist_c, &fAngle); if(fabs(fDist_c) < 1000.0) /* distance too short for a FAI sector */ return -1; double fDistMax = fDist_c/FAI_NORMAL_PERCENTAGE; double fDistMin = fDist_c/(1.0-2.0*FAI28_45Threshold); double fDelta_Dist = 2.0* fDist_c*fFAI_Percentage / (double)(FAI_SECTOR_STEPS-1); double fA, fB; double fMinLeg, fMaxLeg,fDiff=0; double dir = -1.0; BOOL bBigFAISector = false; if(fDistMax > FAI28_45Threshold) { bBigFAISector = true; fDistMax = fDist_c/FAI_BIG_PERCENTAGE; } if(fDistMin < FAI28_45Threshold) { fDistMin = fDist_c/(1.0-2.0*FAI_NORMAL_PERCENTAGE); } if (iOpposite >0) { dir = 1.0; } //#define HELP_LINES #ifdef HELP_LINES int x2,y2, style; FindLatitudeLongitude(lat1, lon1, AngleLimit360 (fAngle), fDist_c/2, &lat_d, &lon_d); x1 = (lon_d - lon_c)*fastcosine(lat_d); y1 = (lat_d - lat_c); FindLatitudeLongitude(lat_d, lon_d, AngleLimit360 (fAngle-90.0), fDist_c, &lat_d, &lon_d); x2 = (lon_d - lon_c)*fastcosine(lat_d); y2 = (lat_d - lat_c); Surface.DrawLine(rc, x1, y1, x2, y2, style); #endif /******************************************************************** * right below threshold 1 ********************************************************************/ fA = fDistMin; if(fDistMax > FAI28_45Threshold) fB = FAI28_45Threshold; else fB = fDistMax ; if(fA<fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_a = FAI_NORMAL_PERCENTAGE * fDistTri; fDist_b = fDistTri - fDist_a - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri += fDelta_Dist; } } /******************************************************************** * right threshold extender 2 ********************************************************************/ if(fDistMin < FAI28_45Threshold) if(bBigFAISector && (fDistMin < FAI28_45Threshold)) { fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE; fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE; fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE; fB = FAI28_45Threshold-fMaxLeg-fDist_c; if(fB < fMinLeg) fB = fMinLeg; fDist_a = fA; fDelta_Dist = (fB-fA) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_b = FAI28_45Threshold - fDist_a - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a += fDelta_Dist; } } /******************************************************************** * right above threshold 3 ********************************************************************/ if(bBigFAISector) { fA = FAI28_45Threshold; if(fDistMin > fA) fA= fDistMin; fB =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE); if(fA < fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fDist_a = fDistTri-fMinLeg-fDist_c;; fDist_b = fMinLeg; if(fDist_a > fMaxLeg) { fDiff = fDist_a - fMaxLeg; fDist_b+=fDiff; fDist_a-=fDiff; } LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_a*fDist_a + fDist_c*fDist_c - fDist_b*fDist_b )/(2.0*fDist_c*fDist_a); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_a, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri += fDelta_Dist; } } } /******************************************************************** * TOP limited round 4 ********************************************************************/ if(fDistMax <= FAI28_45Threshold) fDist_b = fDistMax*(1.0-2*FAI_NORMAL_PERCENTAGE); else fDist_b = fDistMax*FAI_BIG_MAX_PERCENTAGE; fDist_a = fDistMax-fDist_b-fDist_c; fDelta_Dist = (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a -= fDelta_Dist; fDist_b += fDelta_Dist; } /******************************************************************** * calc left leg ********************************************************************/ /******************************************************************** * LEFT above threshold 5 ********************************************************************/ if(bBigFAISector) { fB = FAI28_45Threshold; if( fB < fDistMin) fB = fDistMin; fA =fDist_c/(1- FAI_BIG_PERCENTAGE-FAI_BIG_MAX_PERCENTAGE); if(fA >= fB) { fDelta_Dist =(fA-fB)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fA; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fDist_a = fDistTri-fMinLeg-fDist_c; fDist_b = fMinLeg; if(fDist_a > fMaxLeg) { fDiff = fDist_a - fMaxLeg; fDist_b+=fDiff; fDist_a-=fDiff; } LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri -= fDelta_Dist; } } } /******************************************************************** * LEFT threshold extender 6 ********************************************************************/ if(fDistMin < FAI28_45Threshold) if((fDistMin < FAI28_45Threshold) && (FAI28_45Threshold < fDistMax)) { fMaxLeg = FAI28_45Threshold*FAI_BIG_MAX_PERCENTAGE; fMinLeg = FAI28_45Threshold*FAI_BIG_PERCENTAGE; fA = FAI28_45Threshold*FAI_NORMAL_PERCENTAGE; fB = FAI28_45Threshold-fMaxLeg-fDist_c; if(fB < fMinLeg) fB = fMinLeg; fDist_b = fB; fDelta_Dist = (fA-fB) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_a = FAI28_45Threshold - fDist_b - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_b += fDelta_Dist; } } /******************************************************************** * LEFT below threshold 7 ********************************************************************/ fA = fDistMin; if(fDistMax > FAI28_45Threshold) fB = FAI28_45Threshold; else fB = fDistMax ; if(fA<fB) { fDelta_Dist =(fB-fA)/ (double)(FAI_SECTOR_STEPS-1); fDistTri = fB; for(i =0 ;i < FAI_SECTOR_STEPS; i++) { fDist_b = FAI_NORMAL_PERCENTAGE * fDistTri; fDist_a = fDistTri - fDist_b - fDist_c; LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDistTri -= fDelta_Dist; } } /******************************************************************** * low open PEAK round 8 ********************************************************************/ if(fDistMin >FAI28_45Threshold) { fDist_b = fDistMin*FAI_BIG_PERCENTAGE; fDist_a = fDistMin-fDist_b-fDist_c; fDelta_Dist = (fDist_b-fDist_a) / (double)(FAI_SECTOR_STEPS-1); for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, Pt1); LKASSERT(iPolyPtr < MAX_FAI_SECTOR_PTS); apSectorPolygon[iPolyPtr++] = Pt1; fDist_a += fDelta_Dist; fDist_b -= fDelta_Dist; } } /******************************************************************** * draw polygon ********************************************************************/ LKPen hpSectorPen(PEN_SOLID, IBLSCALE(2), fillcolor ); LKPen hpOldPen = Surface.SelectObject(hpSectorPen); LKBrush hpOldBrush = Surface.SelectObject(LKBrush_Hollow); Surface.Polygon(apSectorPolygon,iPolyPtr,rc); Surface.SelectObject(hpOldPen); Surface.SelectObject(hpOldBrush); hpSectorPen.Release(); /******************************************************************** * calc round leg grid ********************************************************************/ hpSectorPen.Create(PEN_SOLID, (1), RGB_BLACK ); Surface.SelectObject(hpSectorPen); Surface.SetTextColor(RGB_BLACK); double fTic= 1/DISTANCEMODIFY; if(fDist_c > 5/DISTANCEMODIFY) fTic = 10/DISTANCEMODIFY; if(fDist_c > 50/DISTANCEMODIFY) fTic = 25/DISTANCEMODIFY; if(fDist_c > 100/DISTANCEMODIFY) fTic = 50/DISTANCEMODIFY; // if(fDist_c > 200/DISTANCEMODIFY) fTic = 100/DISTANCEMODIFY; if(fDist_c > 500/DISTANCEMODIFY) fTic = 250/DISTANCEMODIFY; POINT line[2]; BOOL bFirstUnit = true; LKASSERT(fTic!=0); fDistTri = ((int)(fDistMin/fTic)+1) * fTic ; LKFont hfOld = Surface.SelectObject(LK8PanelUnitFont); int iCnt = 0; while(fDistTri <= fDistMax) { TCHAR text[180]; SIZE tsize; if(bFirstUnit) _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit())); else _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY)); bFirstUnit = false; Surface.GetTextSize(text, _tcslen(text), &tsize); int j=0; if(fDistTri < FAI28_45Threshold) { fDist_b = fDistTri*FAI_NORMAL_PERCENTAGE; fDist_a = fDistTri-fDist_b-fDist_c; fDelta_Dist = (fDist_a-fDist_b) / (double)(FAI_SECTOR_STEPS-1); } else { fMaxLeg = fDistTri*FAI_BIG_MAX_PERCENTAGE; fMinLeg = fDistTri*FAI_BIG_PERCENTAGE; fA = fMaxLeg; fB = fDistTri-fA-fDist_c; fDist_a = fA; fDist_b = fB; if(fB < fMinLeg) { fDiff = fMinLeg-fB; fB+=2*fDiff; fDist_b += fDiff; fDist_a -= fDiff; } if(fB > fMaxLeg) { fDiff = fB - fMaxLeg; fB+=2*fDiff; fDist_b-=fDiff; fDist_a+=fDiff; } fFAI_Percentage = FAI_BIG_PERCENTAGE; fDelta_Dist = (fA-fB) / (double)(FAI_SECTOR_STEPS-1); } for(i =0 ;i < FAI_SECTOR_STEPS; i++) { LKASSERT(fDist_c*fDist_b!=0); cos_alpha = ( fDist_b*fDist_b + fDist_c*fDist_c - fDist_a*fDist_a )/(2.0*fDist_c*fDist_b); alpha = acos(cos_alpha)*180/PI * dir; FindLatitudeLongitude(lat1, lon1, AngleLimit360( fAngle + alpha ) , fDist_b, &lat_d, &lon_d); MapWindow::LatLon2Screen(lon_d, lat_d, line[0]); if(j> 0) { ForcedClipping=true; Surface.DrawLine(PEN_DASH, NIBLSCALE(1), line[0] , line[1] , RGB_BLACK, rc); ForcedClipping=false; } if(j==0) { Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); j=1; } // TCHAR text[180]; SIZE tsize; if(iCnt==0) _stprintf(text, TEXT("%i%s"), (int)(fDistTri*DISTANCEMODIFY), Units::GetUnitName(Units::GetUserDistanceUnit())); else _stprintf(text, TEXT("%i"), (int)(fDistTri*DISTANCEMODIFY)); Surface.GetTextSize(text, _tcslen(text), &tsize); if(i == 0) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); if(iCnt > 1) if(i == FAI_SECTOR_STEPS-1) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); if(iCnt > 2) if((i== (FAI_SECTOR_STEPS/2))) Surface.DrawText(line[0].x, line[0].y, text, _tcslen(text)); line[1] = line[0]; fDist_a -= fDelta_Dist; fDist_b += fDelta_Dist; } fDistTri+=fTic;iCnt++; // if((iCnt %2) ==0) // DrawText(hdc, line[0].x, line[0].y, ETO_OPAQUE, NULL, text, _tcslen(text), NULL); } Surface.SelectObject(hfOld); Surface.SelectObject(hpOldPen); return 0; }
void Statistics::DrawXGrid(LKSurface& Surface, const RECT& rc, const double tic_step, const double zero, const int Style, const double unit_step, bool draw_units) { if(INVERTCOLORS || IsDithered()) Surface.SelectObject(LK_BLACK_PEN); POINT line[2]; double xval; SIZE tsize; int xmin, ymin, xmax, ymax; if (!tic_step) return; LKASSERT(tic_step!=0); // bool do_units = ((x_max-zero)/tic_step)<10; for (xval=zero; xval<= x_max; xval+= tic_step) { xmin = (int)((xval-x_min)*xscale)+rc.left+BORDER_X; ymin = rc.top; xmax = xmin; ymax = rc.bottom; line[0].x = xmin; line[0].y = ymin; line[1].x = xmax; line[1].y = ymax-BORDER_Y; // STYLE_THINDASHPAPER if ((xval< x_max) && (xmin>=rc.left+BORDER_X) && (xmin<=rc.right)) { StyleLine(Surface, line[0], line[1], Style, rc); if (draw_units) { TCHAR unit_text[MAX_PATH]; FormatTicText(unit_text, xval*unit_step/tic_step, unit_step); // SetBkMode(hdc, OPAQUE); Surface.GetTextSize(unit_text, &tsize); Surface.SetBackgroundOpaque(); Surface.DrawText(xmin-tsize.cx/2, ymax-tsize.cy, unit_text); Surface.SetBackgroundTransparent(); } } } for (xval=zero-tic_step; xval>= x_min; xval-= tic_step) { xmin = (int)((xval-x_min)*xscale)+rc.left+BORDER_X; ymin = rc.top; xmax = xmin; ymax = rc.bottom; line[0].x = xmin; line[0].y = ymin; line[1].x = xmax; line[1].y = ymax-BORDER_Y; // STYLE_THINDASHPAPER if ((xval> x_min) && (xmin>=rc.left+BORDER_X) && (xmin<=rc.right)) { StyleLine(Surface, line[0], line[1], Style, rc); if (draw_units) { TCHAR unit_text[MAX_PATH]; FormatTicText(unit_text, xval*unit_step/tic_step, unit_step); // SetBkMode(hdc, OPAQUE); Surface.GetTextSize(unit_text, &tsize); Surface.SetBackgroundOpaque(); Surface.DrawText(xmin-tsize.cx/2, ymax-tsize.cy, unit_text); Surface.SetBackgroundTransparent(); } } } }
bool MapWindow::TextInBox(LKSurface& Surface, const RECT *clipRect, const TCHAR* Value, int x, int y, TextInBoxMode_t *Mode, bool noOverlap) { SIZE tsize; RECT brect; LKSurface::OldFont oldFont {}; bool drawn=false; if ((x<clipRect->left-WPCIRCLESIZE) || (x>clipRect->right+(WPCIRCLESIZE*3)) || (y<clipRect->top-WPCIRCLESIZE) || (y>clipRect->bottom+WPCIRCLESIZE)) { return drawn; } if (Mode == NULL) return false; const auto hbOld = Surface.SelectObject(LKBrush_White); const auto hpOld = Surface.SelectObject(LK_BLACK_PEN); if (Mode->Reachable){ if (Appearance.IndLandable == wpLandableDefault){ x += 5; // make space for the green circle }else if (Appearance.IndLandable == wpLandableAltA){ x += 0; } } // landable waypoint label inside white box if (!Mode->NoSetFont) { if (Mode->Border || Mode->WhiteBold){ oldFont = Surface.SelectObject(MapWaypointBoldFont); } else { oldFont = Surface.SelectObject(MapWaypointFont); } } Surface.GetTextSize(Value, &tsize); if (Mode->AlligneRight){ x -= tsize.cx; } else if (Mode->AlligneCenter){ x -= tsize.cx/2; y -= tsize.cy/2; } bool notoverlapping = true; if (Mode->Border || Mode->WhiteBorder){ POINT offset; brect.left = x-2; brect.right = brect.left+tsize.cx+4; brect.top = y+((tsize.cy+4)>>3)-2; brect.bottom = brect.top+3+tsize.cy-((tsize.cy+4)>>3); if (Mode->AlligneRight) x -= 3; if (TextInBoxMoveInView(clipRect, &offset, &brect)){ x += offset.x; y += offset.y; } #if CLIP_TEXT if (y>=clipRect->bottom || brect.bottom>=clipRect->bottom ) return false; #endif notoverlapping = checkLabelBlock(&brect); if (!noOverlap || notoverlapping) { LKSurface::OldPen oldPen; if (Mode->Border) { oldPen = Surface.SelectObject(LKPen_Black_N1); } else { oldPen = Surface.SelectObject(LK_WHITE_PEN); } Surface.RoundRect(brect, NIBLSCALE(4), NIBLSCALE(4)); Surface.SelectObject(oldPen); if (Mode->SetTextColor) Surface.SetTextColor(Mode->Color); else Surface.SetTextColor(RGB_BLACK); #ifndef __linux__ Surface.DrawText(x, y, Value); #else Surface.DrawText(x, y+NIBLSCALE(1), Value); #endif drawn=true; } } else if (Mode->FillBackground) {
void Statistics::DrawYGrid(LKSurface& Surface, const RECT& rc, const double tic_step, const double zero, const int Style, const double unit_step, bool draw_units) { POINT line[2]; SIZE tsize; double yval; if(INVERTCOLORS || IsDithered()) Surface.SelectObject(LK_BLACK_PEN); int xmin, ymin, xmax, ymax; if (!tic_step) return; for (yval=zero; yval<= y_max; yval+= tic_step) { xmin = rc.left; ymin = (int)((y_max-yval)*yscale)+rc.top -BORDER_Y; xmax = rc.right; ymax = ymin; line[0].x = xmin+BORDER_X; line[0].y = ymin; line[1].x = xmax; line[1].y = ymax; // STYLE_THINDASHPAPER if ((yval< y_max) && (ymin>=rc.top) && (ymin<=rc.bottom-BORDER_Y)) { StyleLine(Surface, line[0], line[1], Style, rc); if (draw_units) { TCHAR unit_text[MAX_PATH]; FormatTicText(unit_text, yval*unit_step/tic_step, unit_step); Surface.GetTextSize(unit_text, &tsize); Surface.SetBackgroundOpaque(); Surface.DrawText(xmin, ymin-tsize.cy/2, unit_text); Surface.SetBackgroundTransparent(); } } } for (yval=zero-tic_step; yval>= y_min; yval-= tic_step) { xmin = rc.left; ymin = (int)((y_max-yval)*yscale)+rc.top-BORDER_Y; xmax = rc.right; ymax = ymin; line[0].x = xmin+BORDER_X; line[0].y = ymin; line[1].x = xmax; line[1].y = ymax; // STYLE_THINDASHPAPER if ((yval> y_min) && (ymin>=rc.top) && (ymin<=rc.bottom-BORDER_Y)) { StyleLine(Surface, line[0], line[1], Style, rc); if (draw_units) { TCHAR unit_text[MAX_PATH]; FormatTicText(unit_text, yval*unit_step/tic_step, unit_step); Surface.GetTextSize(unit_text, &tsize); Surface.SetBackgroundOpaque(); Surface.DrawText(xmin, ymin-tsize.cy/2, unit_text); Surface.SetBackgroundTransparent(); } } } }
void MapWindow::DrawVisualGlide(LKSurface& Surface, const DiagrammStruct& sDia) { const RECT& rci = sDia.rc; unsigned short numboxrows = 1; #if BUGSTOP LKASSERT(Current_Multimap_SizeY < SIZE4); #endif switch (Current_Multimap_SizeY) { case SIZE0: case SIZE1: numboxrows = 3; break; case SIZE2: numboxrows = 2; break; case SIZE3: numboxrows = 1; break; case SIZE4: return; default: LKASSERT(0); break; } if (!ScreenLandscape) { numboxrows++; if (numboxrows > 3) numboxrows = 3; } TCHAR tmpT[30]; line1Font = LK8VisualTopFont; line2Font = LK8VisualBotFont; SIZE textSizeTop, textSizeBot; Surface.SelectObject(line1Font); _stprintf(tmpT, _T("MMMM")); Surface.GetTextSize(tmpT, &textSizeTop); Surface.SelectObject(line2Font); _stprintf(tmpT, _T("55.5%s 79%s%s "), Units::GetDistanceName(), MsgToken(2179), MsgToken(2183)); Surface.GetTextSize(tmpT, &textSizeBot); // we can cut the waypoint name, but not the value data, so we use the second row of data // to size the box for everything. maxtSizeX = textSizeBot.cx; int a = (rci.right-rci.left) / (textSizeBot.cx+BOXINTERVAL); int b = (rci.right-rci.left) - a * (textSizeBot.cx)-(BOXINTERVAL * (a + 1)); boxSizeX = textSizeBot.cx + (b / (a + 1)); boxSizeY = textSizeTop.cy + 1; // single line (wp name) + distance from bottombar if (numboxrows > 1) { boxSizeY += (textSizeBot.cy * (numboxrows - 1)) - NIBLSCALE(2); if (numboxrows > 2) boxSizeY -= NIBLSCALE(1); } #if DEBUG_SCR StartupStore(_T("boxX=%d boxY=%d \n"), boxSizeX, boxSizeY); #endif #if DEBUG_SCR StartupStore(_T("VG AREA LTRB: %d,%d %d,%d\n"), rci.left, rci.top, rci.right, rci.bottom); #endif const auto oldBrush = Surface.SelectObject(LKBrush_White); const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); BrushReference brush_back; if (!INVERTCOLORS) { brush_back = LKBrush_Black; } else { brush_back = LKBrush_Nlight; } Surface.FillRect(&rci, brush_back); POINT center, p1, p2; center.y = rci.top + (rci.bottom - rci.top) / 2; center.x = rci.left + (rci.right - rci.left) / 2; // numSlotX is the number items we can print horizontally. unsigned short numSlotX = (rci.right - rci.left) / (boxSizeX + BOXINTERVAL); if (numSlotX > MAXBSLOT) numSlotX = MAXBSLOT; #if BUGSTOP LKASSERT(numSlotX > 0); #endif if (numSlotX == 0) return; unsigned short boxInterval = ((rci.right - rci.left)-(boxSizeX * numSlotX)) / (numSlotX + 1); unsigned short oddoffset = ( (rci.right-rci.left) - (boxSizeX * numSlotX) - boxInterval * (numSlotX + 1)) / 2; /* #if BUGSTOP // not really harmful LKASSERT(oddoffset<=boxInterval); #endif */ #if DEBUG_SCR StartupStore(_T("numSlotX=%d ScreenSizeX=%d boxSizeX=%d interval=%d offset=%d\n"), numSlotX, ScreenSizeX, boxSizeX, boxInterval, oddoffset); #endif unsigned int t; // The horizontal grid unsigned int slotCenterX[MAXBSLOT + 1]; for (t = 0; t < numSlotX; t++) { slotCenterX[t] = (t * boxSizeX) + boxInterval * (t + 1)+(boxSizeX / 2) + oddoffset+rci.left; #if DEBUG_SCR StartupStore(_T("slotCenterX[%d]=%d\n"), t, slotCenterX[t]); #endif } // Vertical coordinates of each up/down subwindow, excluding center line int upYtop = rci.top; #if MIDCENTER int upYbottom = center.y + (boxSizeY / 2); int downYtop = center.y - (boxSizeY / 2); #else int upYbottom = center.y - CENTERYSPACE; int downYtop = center.y + CENTERYSPACE; #endif int upSizeY = upYbottom - upYtop - (boxSizeY); ; int downYbottom = rci.bottom; int downSizeY = downYbottom - downYtop - (boxSizeY); ; #if 0 // Reassign dynamically the vertical scale for each subwindow size double vscale = 1000 * (100 - Current_Multimap_SizeY) / 100; #else // Set the vertical range double vscale; if (Units::GetUserAltitudeUnit() == unFeet) vscale = (1000 / TOFEET); else vscale = 300.0; #endif Surface.SetBackgroundTransparent(); RECT trc = rci; // Top part of visual rect, target is over us=unreachable=red trc.top = rci.top; trc.bottom = center.y - 1; #ifndef DITHER RenderSky(Surface, trc, RGB_WHITE, LKColor(150, 255, 150), GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE, GC_NO_COLOR_STEPS / 2); #endif // Bottom part, target is below us=reachable=green trc.top = center.y + 1; trc.bottom = rci.bottom; #ifndef DITHER RenderSky(Surface, trc, LKColor(255, 150, 150), RGB_WHITE, GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE,GC_NO_COLOR_STEPS / 2); #endif // Draw center line p1.x = rci.left + 1; p1.y = center.y; p2.x = rci.right - 1; p2.y = center.y; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); #if DEBUG_SCR StartupStore(_T("... Center line: Y=%d\n"), center.y); #endif Surface.SelectObject(line1Font); Surface.SelectObject(LKPen_Black_N0); ResetVisualGlideGlobals(); short res = GetVisualGlidePoints(numSlotX); if (res == INVALID_VALUE) { #if DEBUG_DVG StartupStore(_T("...... GVGP says not ready, wait..\n")); #endif return; } if (res == 0) { #if DEBUG_DVG StartupStore(_T("...... GVGP says no data available!\n")); #endif return; } // Print them all! int offset = (boxSizeY / 2) + CENTERYSPACE; LKBrush bcolor; LKColor rgbcolor, textcolor; int wp; unsigned short zeroslot = 0; double minbrgdiff = 999.0; double minabrgdiff = 999.0; // absolute never negative for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } double brgdiff = WayPointCalc[wp].Bearing - DrawInfo.TrackBearing; // this check is worthless if (brgdiff < -180.0) { brgdiff += 360.0; } else { if (brgdiff > 180.0) brgdiff -= 360.0; } double abrgdiff = brgdiff; if (abrgdiff < 0) abrgdiff *= -1; if (abrgdiff < minabrgdiff) { zeroslot = n; minabrgdiff = abrgdiff; minbrgdiff = brgdiff; } } // Draw vertical line #define DEGRANGE 10 // degrees left and right to perfect target if (minabrgdiff < 1) { p1.x = slotCenterX[zeroslot]; } else { // set fullscale range if (minabrgdiff > DEGRANGE) { minabrgdiff = DEGRANGE; if (minbrgdiff < 0) minbrgdiff = -1 * DEGRANGE; else minbrgdiff = DEGRANGE; } // we shift of course in the opposite direction p1.x = slotCenterX[zeroslot]-(int) ((boxSizeX / (DEGRANGE * 2)) * minbrgdiff); } p2.x = p1.x; p1.y = rci.top + 1; p2.y = rci.bottom - 1; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } #if DEBUG_DVG StartupStore(_T("... DVG PRINT [%d]=%d <%s>\n"), n, wp, WayPointList[wp].Name); #endif Sideview_VGWpt[n] = wp; double altdiff = WayPointCalc[wp].AltArriv[AltArrivMode]; int ty; #if DEBUG_SCR StartupStore(_T("... wp=<%s>\n"), WayPointList[wp].Name); #endif // Since terrain can be approximated due to low precision maps, or waypoint position or altitude error, // we have a common problem: we get an obstacle to get to the waypoint because it is // positioned "BELOW" the terrain itself. We try to reduce this problem here. #define SAFETERRAIN 50 // Positive arrival altitude for the waypoint, upper window if (altdiff >= 0) { if (altdiff == 0)altdiff = 1; double d = vscale / altdiff; if (d == 0) d = 1; ty = upYbottom - (int) ((double) upSizeY / d)-(boxSizeY / 2); #if DEBUG_SCR StartupStore(_T("... upYbottom=%d upSizeY=%d / (vscale=%f/altdiff=%f = %f) =- %d ty=%d offset=%d\n"), upYbottom, upSizeY, vscale, altdiff, d, (int) ((double) upSizeY / d), ty, offset); #endif if ((ty - offset) < upYtop) ty = upYtop + offset; if ((ty + offset) > upYbottom) ty = upYbottom - offset; #if DEBUG_SCR StartupStore(_T("... upYtop=%d upYbottom=%d final ty=%d\n"), upYtop, upYbottom, ty); #endif // // This is too confusing. We want simple colors, not shaded // rgbcolor = MixColors( LKColor(50,255,50), LKColor(230,255,230), altdiff/(vscale-50)); // if (altdiff <= SAFETERRAIN) { rgbcolor = RGB_LIGHTYELLOW; } else { if (!CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, WayPointCalc[wp].Distance, WayPointCalc[wp].Bearing)) { rgbcolor = RGB_LIGHTRED; } else { #ifdef DITHER rgbcolor = RGB_WHITE; #else rgbcolor = RGB_LIGHTGREEN; #endif } } bcolor.Create(rgbcolor); } else { double d = vscale / altdiff; if (d == 0) d = -1; ty = downYtop - (int) ((double) downSizeY / d)+(boxSizeY / 2); // - because the left part is negative, we are really adding. if ((ty - offset) < downYtop) ty = downYtop + offset; if ((ty + offset) > downYbottom) ty = downYbottom - offset; #ifdef DITHER rgbcolor = RGB_WHITE; // negative part, no need to render dark #else rgbcolor = RGB_LIGHTRED; #endif bcolor.Create(rgbcolor); } TCHAR line2[40], line3[40]; TCHAR value[40], unit[30]; TCHAR name[NAME_SIZE + 1]; double ar = (WayPointCalc[wp].AltArriv[AltArrivMode] * ALTITUDEMODIFY); _tcscpy(name, WayPointList[wp].Name); CharUpper(name); if (IsSafetyAltitudeInUse(wp)) textcolor = RGB_DARKBLUE; else textcolor = RGB_BLACK; switch (numboxrows) { case 0: #if BUGSTOP LKASSERT(0); #endif return; case 1: // 1 line: waypoint name VGTextInBox(Surface, n, 1, name, NULL, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 2: // 2 lines: waypoint name + altdiff LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line2, _T("%s "), value); else _stprintf(line2, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line2, value); } else { _stprintf(line2, _T("%s ---"), value); } VGTextInBox(Surface, n, 2, name, line2, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 3: // 3 lines: waypoint name + dist + altdiff LKFormatDist(wp, false, value, unit); _stprintf(line2, _T("%s%s"), value, unit); LKFormatBrgDiff(wp, false, value, unit); _stprintf(tmpT, _T(" %s%s"), value, unit); _tcscat(line2, tmpT); LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line3, _T("%s "), value); else _stprintf(line3, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line3, value); } else { _stprintf(line3, _T("%s ---"), value); } VGTextInBox(Surface, n, 3, name, line2, line3, slotCenterX[n], ty, textcolor, bcolor); break; default: #if BUGSTOP LKASSERT(0); #endif return; } } // for numSlotX // Cleanup and return Surface.SelectObject(oldBrush); Surface.SelectObject(oldPen); return; }
void RenderAirspaceTerrain(LKSurface& Surface, double PosLat, double PosLon, double brg, DiagrammStruct* psDiag) { RECT rc = psDiag->rc; //rc.bottom +=BORDER_Y; double range = psDiag->fXMax - psDiag->fXMin; // km double hmax = psDiag->fYMax; double lat, lon; int i, j; if (!IsDithered() && IsMultimapTerrain()) { RenderSky(Surface, rc, SKY_HORIZON_COL, SKY_SPACE_COL, GC_NO_COLOR_STEPS); } else { Surface.FillRect(&rc, MapWindow::hInvBackgroundBrush[BgMapColor]); } FindLatitudeLongitude(PosLat, PosLon, brg, psDiag->fXMin, &lat, &lon); POINT apTerrainPolygon[AIRSPACE_SCANSIZE_X + 4] = {}; double d_lat[AIRSPACE_SCANSIZE_X] = {}; double d_lon[AIRSPACE_SCANSIZE_X] = {}; double d_h[AIRSPACE_SCANSIZE_X] = {}; #define FRAMEWIDTH 2 RasterTerrain::Lock(); // want most accurate rounding here RasterTerrain::SetTerrainRounding(0, 0); double fj; for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range fj = (double) j * 1.0 / (double) (AIRSPACE_SCANSIZE_X - 1); FindLatitudeLongitude(lat, lon, brg, range*fj, &d_lat[j], &d_lon[j]); d_h[j] = RasterTerrain::GetTerrainHeight(d_lat[j], d_lon[j]); if (d_h[j] == TERRAIN_INVALID) d_h[j] = 0; //@ 101027 BUGFIX hmax = max(hmax, d_h[j]); } RasterTerrain::Unlock(); /******************************************************************************** * scan line ********************************************************************************/ if (IsMultimapAirspace()) Sideview_iNoHandeldSpaces = CAirspaceManager::Instance().ScanAirspaceLineList(d_lat, d_lon, d_h, Sideview_pHandeled, MAX_NO_SIDE_AS); // Sideview_pHandeled[GC_MAX_NO]; else Sideview_iNoHandeldSpaces = 0; #if BUGSTOP LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); #endif if (Sideview_iNoHandeldSpaces >= MAX_NO_SIDE_AS) Sideview_iNoHandeldSpaces = MAX_NO_SIDE_AS - 1; /******************************************************************************** * bubble sort to start with biggest airspaces ********************************************************************************/ int iSizeLookupTable[MAX_NO_SIDE_AS]; for (i = 0; i < Sideview_iNoHandeldSpaces; i++) iSizeLookupTable[i] = i; for (i = 0; i < Sideview_iNoHandeldSpaces; i++) { #if BUGSTOP LKASSERT(iSizeLookupTable[i] < MAX_NO_SIDE_AS); #endif for (j = i; j < Sideview_iNoHandeldSpaces; j++) { #if BUGSTOP LKASSERT(iSizeLookupTable[j] < MAX_NO_SIDE_AS); #endif if (iSizeLookupTable[i] >= MAX_NO_SIDE_AS) continue; if (iSizeLookupTable[j] >= MAX_NO_SIDE_AS) continue; if (Sideview_pHandeled[iSizeLookupTable[i]].iAreaSize < Sideview_pHandeled[iSizeLookupTable[j]].iAreaSize) { int iTmp = iSizeLookupTable[i]; iSizeLookupTable[i] = iSizeLookupTable[j]; iSizeLookupTable[j] = iTmp; } } } /********************************************************************************** * transform into diagram coordinates **********************************************************************************/ double dx1 = (double) (rc.right) / (double) (AIRSPACE_SCANSIZE_X - 1); int x0 = rc.left; LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); for (i = 0; i < Sideview_iNoHandeldSpaces; i++) { Sideview_pHandeled[i].rc.left = (long) ((Sideview_pHandeled[i].rc.left) * dx1) + x0 - FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.right = (long) ((Sideview_pHandeled[i].rc.right) * dx1) + x0 + FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.bottom = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.bottom, psDiag) + FRAMEWIDTH / 2; Sideview_pHandeled[i].rc.top = CalcHeightCoordinat((double) Sideview_pHandeled[i].rc.top, psDiag) - FRAMEWIDTH / 2; Sideview_pHandeled[i].iMaxBase = Sideview_pHandeled[i].rc.bottom; Sideview_pHandeled[i].iMinTop = Sideview_pHandeled[i].rc.top; int iN = Sideview_pHandeled[i].iNoPolyPts; #if BUGSTOP LKASSERT(iN < GC_MAX_POLYGON_PTS); #endif if (iN >= GC_MAX_POLYGON_PTS) iN = GC_MAX_POLYGON_PTS - 1; if (Sideview_pHandeled[i].bRectAllowed == false) { for (j = 0; j < iN; j++) { Sideview_pHandeled[i].apPolygon[j].x = (long) (((Sideview_pHandeled[i].apPolygon[j].x) * dx1) + x0); Sideview_pHandeled[i].apPolygon[j].y = CalcHeightCoordinat((double) Sideview_pHandeled[i].apPolygon[j].y, psDiag); if (j != iN - 1) { if ((j < iN / 2)) { Sideview_pHandeled[i].iMaxBase = min((long) Sideview_pHandeled[i].iMaxBase, (long) Sideview_pHandeled[i].apPolygon[j].y); } else { Sideview_pHandeled[i].iMinTop = max((long) Sideview_pHandeled[i].iMinTop, (long) Sideview_pHandeled[i].apPolygon[j].y); } } } } } /********************************************************************************** * draw airspaces **********************************************************************************/ const auto oldpen = Surface.SelectObject(LK_NULL_PEN); _TCHAR text [80]; LKASSERT(Sideview_iNoHandeldSpaces < MAX_NO_SIDE_AS); for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) { int iSizeIdx = iSizeLookupTable[m]; #if BUGSTOP LKASSERT(iSizeIdx < MAX_NO_SIDE_AS && iSizeIdx >= 0); #endif if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1; int type = Sideview_pHandeled[iSizeIdx].iType; RECT rcd = Sideview_pHandeled[iSizeIdx].rc; LKColor FrameColor; double fFrameColFact; if (Sideview_pHandeled[iSizeIdx].bEnabled) { Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type)); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type)); fFrameColFact = 0.8; FrameColor = MapWindow::GetAirspaceColourByClass(type); } else { Surface.SelectObject(LKBrush_Hollow); Surface.SetTextColor(RGB_GGREY); FrameColor = RGB_GGREY; fFrameColFact = 1.2; } if (INVERTCOLORS) fFrameColFact *= 0.8; else fFrameColFact *= 1.2; LKColor Color = FrameColor.ChangeBrightness(fFrameColFact); LKPen mpen2(PEN_SOLID, FRAMEWIDTH, Color); const auto oldpen2 = Surface.SelectObject(mpen2); if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true) Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom); else Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts); Surface.SelectObject(oldpen2); if (Sideview_pHandeled[iSizeIdx].bEnabled) Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG else Surface.SetTextColor(RGB_GGREY); /*********************************************** * build view overlap for centering text ***********************************************/ rcd.bottom = min(rcd.bottom, Sideview_pHandeled[iSizeIdx].iMaxBase); rcd.top = max(rcd.top, Sideview_pHandeled[iSizeIdx].iMinTop); rcd.left = max(rcd.left, rc.left); rcd.right = min(rcd.right, rc.right); rcd.bottom = min(rcd.bottom, rc.bottom); rcd.top = max(rcd.top, rc.top); SIZE textsize; SIZE aispacesize = {rcd.right - rcd.left, rcd.bottom - rcd.top}; LK_tcsncpy(text, Sideview_pHandeled[iSizeIdx].szAS_Name, NAME_SIZE - 1/* sizeof(text)/sizeof(text[0])*/); Surface.GetTextSize(text, &textsize); int x = rcd.left + aispacesize.cx / 2; ; int y = rcd.top + aispacesize.cy / 2; // int iTextheight = tsize.cy; int iOffset = 0; BOOL blongtext = false; if (aispacesize.cy > (2 * textsize.cy) && (textsize.cx < aispacesize.cx)) { iOffset = textsize.cy / 2; } if ((textsize.cx < aispacesize.cx) && (textsize.cy < aispacesize.cy)) { Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text); blongtext = true; } LK_tcsncpy(text, CAirspaceManager::Instance().GetAirspaceTypeShortText(Sideview_pHandeled[iSizeIdx].iType), NAME_SIZE); Surface.GetTextSize(text, &textsize); if (textsize.cx < aispacesize.cx) { if (2 * textsize.cy < aispacesize.cy) { Surface.DrawText(x - textsize.cx / 2, y + iOffset - textsize.cy / 2, text); } else { if ((textsize.cy < aispacesize.cy) && (!blongtext)) Surface.DrawText(x - textsize.cx / 2, y - iOffset - textsize.cy / 2, text); } } } Surface.SelectObject(oldpen); /********************************************************************************** * draw airspace frames in reversed order **********************************************************************************/ #ifdef OUTLINE_2ND for (int m = 0; m < Sideview_iNoHandeldSpaces; m++) { int iSizeIdx = iSizeLookupTable[Sideview_iNoHandeldSpaces - m - 1]; if (Sideview_pHandeled[iSizeIdx].bEnabled) { #if BUGSTOP LKASSERT(iSizeIdx < MAX_NO_SIDE_AS); #endif if (iSizeIdx >= MAX_NO_SIDE_AS) iSizeIdx = MAX_NO_SIDE_AS - 1; int type = Sideview_pHandeled[iSizeIdx].iType; RECT rcd = Sideview_pHandeled[iSizeIdx].rc; LKColor FrameColor = MapWindow::GetAirspaceColourByClass(type); double fFrameColFact; Surface.SelectObject(LKBrush_Hollow); if (Sideview_pHandeled[iSizeIdx].bEnabled) { // Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(type)); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(type)); fFrameColFact = 0.8; } else { Surface.SetTextColor(RGB_GGREY); FrameColor = RGB_GGREY; fFrameColFact = 1.2; } if (INVERTCOLORS) fFrameColFact *= 0.8; else fFrameColFact *= 1.2; LKColor lColor = FrameColor.ChangeBrightness(fFrameColFact); LKPen mpen2(PEN_SOLID, FRAMEWIDTH, lColor); const auto oldpen2 = Surface.SelectObject(mpen2); if (Sideview_pHandeled[iSizeIdx].bRectAllowed == true) Surface.Rectangle(rcd.left + 1, rcd.top, rcd.right, rcd.bottom); else Surface.Polygon(Sideview_pHandeled[iSizeIdx].apPolygon, Sideview_pHandeled[iSizeIdx].iNoPolyPts); Surface.SelectObject(oldpen2); } } #endif /************************************************************* * draw ground *************************************************************/ // draw ground /********************************************************************* * draw terrain *********************************************************************/ LKPen hpHorizonGround(PEN_SOLID, IBLSCALE(1) + 1, LKColor(126, 62, 50)); LKBrush hbHorizonGround(GROUND_COLOUR); const auto oldPen = Surface.SelectObject(hpHorizonGround); const auto oldBrush = Surface.SelectObject(hbHorizonGround); for (j = 0; j < AIRSPACE_SCANSIZE_X; j++) { // scan range apTerrainPolygon[j].x = iround(j * dx1) + x0; apTerrainPolygon[j].y = CalcHeightCoordinat(d_h[j], psDiag); } apTerrainPolygon[AIRSPACE_SCANSIZE_X].x = iround(AIRSPACE_SCANSIZE_X * dx1) + x0; ; // x0; apTerrainPolygon[AIRSPACE_SCANSIZE_X].y = CalcHeightCoordinat(0, psDiag); //iBottom; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].x = iround(0 * dx1) + x0; //iround(j*dx1)+x0; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 1].y = CalcHeightCoordinat(0, psDiag); //iBottom; apTerrainPolygon[AIRSPACE_SCANSIZE_X + 2] = apTerrainPolygon[0]; static_assert(array_size(apTerrainPolygon) >= AIRSPACE_SCANSIZE_X + 3, "wrong array size"); Surface.Polygon(apTerrainPolygon, AIRSPACE_SCANSIZE_X + 3); Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); /********************************************************************* * draw sea *********************************************************************/ #ifdef MSL_SEA_DRAW // draw sea if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE) { RECT sea = {rc.left, rc.bottom, rc.right, rc.bottom + SV_BORDER_Y}; #ifndef UNDITHER RenderSky(Surface, sea, RGB_STEEL_BLUE, RGB_ROYAL_BLUE, 7); #else RenderSky(Surface, sea, RGB_BLACK, RGB_BLACK, 2); #endif } #else if (psDiag->fYMin < GC_SEA_LEVEL_TOLERANCE) Rectangle(hdc, rc.left, rc.bottom, rc.right, rc.bottom + BORDER_Y); #endif Surface.SetTextColor(Sideview_TextColor); // RGB_MENUTITLEFG }