static void OnPaintAirspacePicto(WindowControl * Sender, LKSurface& Surface){ (void)Sender; WndFrame *wPicto = ((WndFrame *)wf->FindByName(TEXT("frmAirspacePicto"))); LKASSERT(wPicto!=NULL); const RECT rc = wPicto->GetClientRect(); Surface.SelectObject(LKPen_Petrol_C2); Surface.SelectObject(LKBrush_Petrol); Surface.Rectangle(rc.left,rc.top,rc.right,rc.bottom); Surface.SetBkColor(RGB_LIGHTGREY); /**************************************************************** * for drawing the airspace pictorial, we need the original data. * copy contain only base class property, not geo data, * original data are shared ressources ! * for that we need to grant all called methods are thread safe ****************************************************************/ { CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef()); CAirspace* airspace = CAirspaceManager::Instance().GetAirspacesForDetails(); if(airspace) { airspace->DrawPicto(Surface, rc); } } }
static void OnAirspacePaintListItem(WindowControl * Sender, LKSurface& Surface){ TCHAR label[40]; (void)Sender; if (DrawListIndex < AIRSPACECLASSCOUNT){ int i = DrawListIndex; LK_tcsncpy(label, CAirspaceManager::Instance().GetAirspaceTypeText(i), 39); int w0, w1, w2, x0; if (ScreenLandscape) { w0 = 202*ScreenScale; } else { w0 = 225*ScreenScale; } // LKTOKEN _@M789_ = "Warn" w1 = Surface.GetTextWidth(MsgToken(789))+ScreenScale*10; // LKTOKEN _@M241_ = "Display" w2 = Surface.GetTextWidth(MsgToken(241))+ScreenScale*10; x0 = w0-w1-w2; Surface.SetTextColor(RGB_BLACK); Surface.DrawTextClip(2*ScreenScale, 2*ScreenScale, label, x0-ScreenScale*10); if (colormode) { Surface.SelectObject(LK_WHITE_PEN); Surface.SelectObject(LKBrush_White); Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(i)); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(i)); Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale); } else { bool iswarn; bool isdisplay; iswarn = (MapWindow::iAirspaceMode[i]>=2); isdisplay = ((MapWindow::iAirspaceMode[i]%2)>0); if (iswarn) { // LKTOKEN _@M789_ = "Warn" _tcscpy(label, MsgToken(789)); Surface.DrawText(w0-w1-w2, 2*ScreenScale, label); } if (isdisplay) { // LKTOKEN _@M241_ = "Display" _tcscpy(label, MsgToken(241)); Surface.DrawText(w0-w2, 2*ScreenScale, label); } } } }
static void OnAirspacePatternsPaintListItem(WindowControl * Sender, LKSurface& Surface) { (void) Sender; if ((DrawListIndex < NUMAIRSPACEBRUSHES) &&(DrawListIndex >= 0)) { int i = DrawListIndex; Surface.SelectObject(LKBrush_White); Surface.SelectObject(LK_BLACK_PEN); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceBrush(i)); Surface.SetTextColor(LKColor(0x00, 0x00, 0x00)); Surface.Rectangle(100 * ScreenScale, 2 * ScreenScale, 180 * ScreenScale, 22 * ScreenScale); } }
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) { #define PICTO_WIDTH 50 Surface.SetTextColor(RGB_BLACK); if (TaskDrawListIndex < iNO_Tasks) { TCHAR *pToken = NULL; TCHAR *pWClast = NULL; TCHAR *pWClast2 = NULL; TCHAR text[180] = {TEXT("empty")}; TCHAR text1[180] = {TEXT("empty")}; TCHAR text2[180] = {TEXT("empty")}; _tcscpy(text, szTaskStrings [TaskDrawListIndex] ); unsigned int i=0; while (i < _tcslen(text) ) // remove all quotations " { if(text[i]== '"') // quotations found ? { for (unsigned int j= i ; j < _tcslen(text); j++) text[j] = text[j+1]; } i++; } pToken = strsep_r(text, TEXT(","), &pWClast) ; _tcscpy(text1, pToken ); if(*text1 == '\0') _tcscpy(text1, _T("???") ); pToken = strsep_r(pWClast, TEXT(","), &pWClast2) ; // remove takeof point _tcscpy(text2, pWClast2); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); PixelRect rc = { 0, 0, 0, // DLGSCALE(PICTO_WIDTH), static_cast<PixelScalar>(Sender->GetHeight()) }; /******************** * show text ********************/ Surface.SetBackgroundTransparent(); Surface.SetTextColor(RGB_BLACK); Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1); int ytext2 = Surface.GetTextHeight(text1); Surface.SetTextColor(RGB_DARKBLUE); Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2); } }
static void OnAirspaceColoursPaintListItem(WindowControl * Sender, LKSurface& Surface){ (void)Sender; if ((DrawListIndex < NUMAIRSPACECOLORS) &&(DrawListIndex>=0)) { int i = DrawListIndex; Surface.SelectObject(LKBrush_White); Surface.SelectObject(LK_BLACK_PEN); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceSldBrush(i)); // this is the solid brush Surface.SetTextColor(MapWindow::GetAirspaceColour(i)); Surface.Rectangle( 100*ScreenScale, 2*ScreenScale, 180*ScreenScale, 22*ScreenScale); } }
static void OnPaintAirspacePicto(WindowControl * Sender, LKSurface& Surface){ const RECT rc = Sender->GetClientRect(); Surface.SetBkColor(RGB_LIGHTGREY); /**************************************************************** * for drawing the airspace pictorial, we need the original data. * copy contain only base class property, not geo data, * original data are shared ressources ! * for that we need to grant all called methods are thread safe ****************************************************************/ { ScopeLock guard(CAirspaceManager::Instance().MutexRef()); CAirspace* airspace = CAirspaceManager::Instance().GetAirspacesForDetails(); if(airspace) { airspace->DrawPicto(Surface, rc); } } }
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) { #define PICTO_WIDTH 50 Surface.SetTextColor(RGB_BLACK); if ((DrawListIndex < iNO_ELEMENTS) &&(DrawListIndex >= 0)) { int j; static CAirspaceBase airspace_copy; int i = DrawListIndex; LKASSERT(i < MAX_LIST_ITEMS); PixelRect rc = { 0, 0, DLGSCALE(PICTO_WIDTH), static_cast<PixelScalar>(Sender->GetHeight()) }; const CAirspace* pAS = NULL; int HorDist, Bearing, VertDist; double Distance; unsigned int idx = 0; TCHAR text1[180] = {TEXT("empty")}; TCHAR text2[180] = {TEXT("empty")}; TCHAR Comment[80] = {TEXT("")}; TCHAR Comment1[80] = {TEXT("")}; Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); LKASSERT(i < MAX_LIST_ITEMS); switch (Elements[i].type) { case IM_AIRSPACE: pAS = (CAirspace*) Elements[i].ptr; if (pAS) { /*********************************************************************** * here we use a local copy of the airspace, only common property exists ***********************************************************************/ airspace_copy = CAirspaceManager::Instance().GetAirspaceCopy(pAS); // airspace type already in name? if (_tcsnicmp(airspace_copy.Name(), airspace_copy.TypeName(), _tcslen(airspace_copy.TypeName())) == 0) { _stprintf(text1, TEXT("%s"), airspace_copy.Name()); // yes, take name only } else { // fixed strings max. 20 NAME_SIZE 30 => max. 30 char _stprintf(text1, TEXT("%s %s"), airspace_copy.TypeName(), airspace_copy.Name()); } CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment, sizeof (Comment) / sizeof (Comment[0]), airspace_copy.Top()); CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment1, sizeof (Comment1) / sizeof (Comment1[0]), airspace_copy.Base()); CAirspaceManager::Instance().AirspaceCalculateDistance((CAirspace*) pAS, &HorDist, &Bearing, &VertDist); _stprintf(text2, TEXT("%3.1f%s (%s - %s)"), (double) HorDist*DISTANCEMODIFY, Units::GetDistanceName(), Comment1, Comment); //8 + 8+3 21 /**************************************************************** * for drawing the airspace pictorial, we need the original data. * copy contain only base class property, not geo data, * original data are shared ressources ! * for that we need to grant all called methods are thread safe ****************************************************************/ pAS->DrawPicto(Surface, rc); } break; case IM_TASK_PT: case IM_WAYPOINT: idx = -1; LockTaskData(); // protect from external task changes if (Elements[i].type == IM_TASK_PT) { if(ValidTaskPointFast(Elements[i].iIdx)) { idx = Task[Elements[i].iIdx].Index; } } else { if(ValidWayPointFast(Elements[i].iIdx)) { idx = Elements[i].iIdx; } } // This is not a solution. It will avoid a crash but the solution is to understand // why we are getting a wrong idx, eventually. If ever we got a wrong idx! // And then this "fix" should be changed to something more useful, instead of // adopting a totally wrong waypoint for task. assert(idx < WayPointList.size()); if(idx < WayPointList.size()) { if (WayPointList[idx].Comment != NULL) { LK_tcsncpy(Comment, WayPointList[idx].Comment, 30); } else { _tcscpy(Comment, TEXT("")); } DistanceBearing(GPS_INFO.Latitude, GPS_INFO.Longitude, WayPointList[idx].Latitude, WayPointList[idx].Longitude, &Distance, NULL); if (Elements[i].type != IM_TASK_PT) { if (WayPointCalc[idx].IsLandable) { MapWindow::DrawRunway(Surface, &WayPointList[idx], rc, nullptr, 1.5, true); if (WayPointCalc[idx].IsAirport) { // remove spaces from frequency for (j = 1; j < (CUPSIZE_FREQ); j++) if (WayPointList[idx].Freq[CUPSIZE_FREQ - j] == ' ') WayPointList[idx].Freq[CUPSIZE_FREQ - j] = '\0'; if (_tcslen(WayPointList[idx].Freq) > 2) _stprintf(text1, TEXT("%s %s MHz"), WayPointList[idx].Name, WayPointList[idx].Freq); else _stprintf(text1, TEXT("%s"), WayPointList[idx].Name); } else { if (WayPointList[idx].Comment != NULL) _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment); else _stprintf(text1, TEXT("%s"), WayPointList[idx].Name); } if ((WayPointList[idx].RunwayLen >= 10) || (WayPointList[idx].RunwayDir > 0)) { _stprintf(text2, TEXT("%3.1f%s (%i%s %02i/%02i %i%s)"), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName(), (int) (WayPointList[idx].RunwayDir / 10.0 + 0.5), (int) (AngleLimit360(WayPointList[idx].RunwayDir + 180.0) / 10.0 + 0.5), (int) ((double) WayPointList[idx].RunwayLen * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { _stprintf(text2, TEXT("%3.1f%s (%i%s) "), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } }// waypoint isLandable else { MapWindow::DrawWaypointPicto(Surface, rc, &WayPointList[idx]); _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment); _stprintf(text2, TEXT("%3.1f%s (%i%s)"), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } }// Elements IM_TASK else { int iTaskIdx = Elements[i].iIdx; MapWindow::DrawTaskPicto(Surface, iTaskIdx, rc, 3000); int iLastTaskPoint = 0; while (ValidTaskPoint(iLastTaskPoint)) iLastTaskPoint++; iLastTaskPoint--; if (iTaskIdx == 0) { // _@M2301_ "S" # S = Start Task point _stprintf(text1, TEXT("%s: (%s)"), MsgToken(2301), WayPointList[idx].Name); _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), StartRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { if (iTaskIdx == iLastTaskPoint) { // _@M2303_ "F" // max 30 30 => max 60 char _stprintf(text1, TEXT("%s: (%s) "), MsgToken(2303), WayPointList[idx].Name); _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), FinishRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { // _@M2302_ "T" # F = Finish point // max 30 30 => max 60 char _stprintf(text1, TEXT("%s%i: (%s) "), MsgToken(2302), iTaskIdx, WayPointList[idx].Name); double SecRadius = 0; SecRadius = SectorRadius; if (AATEnabled) { if (Task[iTaskIdx].AATType == SECTOR) SecRadius = Task[iTaskIdx].AATSectorRadius; else SecRadius = Task[iTaskIdx].AATCircleRadius; } _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), SecRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } } } } UnlockTaskData(); // protect from external task changes break; } /******************** * show text ********************/ Surface.SetBackgroundTransparent(); Surface.SetTextColor(RGB_BLACK); Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1); int ytext2 = Surface.GetTextHeight(text1); Surface.SetTextColor(RGB_DARKBLUE); Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2); } }
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; auto hfOldFnt = Surface.SelectObject(LK8PanelUnitFont/* Sender->GetFont()*/); int *iSplit = &Multimap_SizeY[Get_Current_Multimap_Type()]; 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: if (Sideview_iNoHandeldSpaces) { bool bShow = false; for (int k = 0; k <= Sideview_iNoHandeldSpaces; k++) { if (Sideview_pHandeled[k].psAS != NULL) { if (PtInRect(&(Sideview_pHandeled[k].rc), startScreen)) { dlgAddMultiSelectListItem((long*) Sideview_pHandeled[k].psAS, 0, IM_AIRSPACE, 0); bShow = true; } } } if (bShow) { /* * we can't show dialog from Draw thread * instead, new event is queued, dialog will be popup by main thread */ InputEvents::processGlideComputer(GCE_POPUP_MULTISELECT); // reset event, otherwise Distance/height zoom mod are also triggered LKevent = LKEVENT_NONE; } } if (LKevent != LKEVENT_NONE) { if (PtInRect(&rc, startScreen)) { bHeightScale = !bHeightScale; } else 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); const auto 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, &tsize); TxYPt.x = (rc.right - rc.left - tsize.cx) / 2; TxYPt.y = (rc.bottom - rc.top) / 2; Surface.SetBackgroundTransparent(); Surface.DrawText(TxYPt.x, TxYPt.y - 20, 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.SetBackgroundTransparent(); Surface.SetTextColor(txtCol); Surface.SelectObject(LK8PanelUnitFont); _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); Surface.SetBkColor(RGB_WHITE); if (!bInvCol) Surface.SetBackgroundOpaque(); /**************************************************************************************************** * 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, &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); } } Surface.SetBackgroundTransparent(); /**************************************************************************************************** * 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, &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); } } /**************************************************************************************************** * draw side elements ****************************************************************************************************/ Surface.SetTextColor(Sideview_TextColor); Surface.SetBackgroundOpaque(); const auto hfOld2 = Surface.SelectObject(LK8InfoNormalFont); // DrawTelescope ( hdc, iAS_Bearing-90.0, rc.right - NIBLSCALE(13), rc.top + NIBLSCALE(58)); Surface.SelectObject(hfOld2); Surface.SetBackgroundTransparent(); 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.SetBackgroundOpaque(); const auto 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, &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); /**************************************************************************************************** * 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, &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); 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.SetBackgroundTransparent(); Surface.SelectObject(hfOldFnt/* Sender->GetFont()*/); }