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::RenderTask(LKSurface& Surface, const RECT& rc, const bool olcmode) { int i, j; unsigned int ui; double fXY_Scale = 1.5; double lat1 = 0; double lon1 = 0; double lat2 = 0; double lon2 = 0; double x1, y1, x2=0, y2=0; double lat_c, lon_c; double aatradius[MAXTASKPOINTS]; // find center ResetScale(); if ( (!ValidTaskPoint(0) || !ValidTaskPoint(1)) && !olcmode) { DrawNoData(Surface,rc); return; } for (i=0; i<MAXTASKPOINTS; i++) { aatradius[i]=0; } bool nowaypoints = true; for (i=0; i<MAXTASKPOINTS; i++) { if (ValidTaskPoint(i)) { lat1 = WayPointList[Task[i].Index].Latitude; lon1 = WayPointList[Task[i].Index].Longitude; ScaleYFromValue(rc, lat1); ScaleXFromValue(rc, lon1); nowaypoints = false; } } if (nowaypoints ) { DrawNoData(Surface, rc); return; } 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(LK8InfoNormalFont); lat_c = (y_max+y_min)/2; lon_c = (x_max+x_min)/2; int nwps = 0; // 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 (i=0; i<MAXTASKPOINTS; i++) { if (ValidTaskPoint(i)) { nwps++; lat1 = WayPointList[Task[i].Index].Latitude; lon1 = WayPointList[Task[i].Index].Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); ScaleXFromValue(rc, x1*fXY_Scale); ScaleYFromValue(rc, y1*fXY_Scale); if (AATEnabled) { double aatlat; double aatlon; double bearing; double radius; if (ValidTaskPoint(i+1)) { if (Task[i].AATType == SECTOR) radius = Task[i].AATSectorRadius; else radius = Task[i].AATCircleRadius; for (j=0; j<4; j++) { bearing = j*360.0/4; FindLatitudeLongitude(WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, bearing, radius, &aatlat, &aatlon); x1 = (aatlon-lon_c)*fastcosine(aatlat); y1 = (aatlat-lat_c); ScaleXFromValue(rc, x1); ScaleYFromValue(rc, y1); if (j==0) { aatradius[i] = fabs(aatlat-WayPointList[Task[i].Index].Latitude); } } } else { aatradius[i] = 0; } } } } 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); // draw aat areas if (AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); #ifdef HAVE_HATCHED_BRUSH Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(AATASK)); #else Surface.SelectObject(LKBrush_Yellow); #endif Surface.SelectObject(LK_WHITE_PEN); if (Task[i].AATType == SECTOR) { Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc, Task[i].AATStartRadial, Task[i].AATFinishRadial); } else { Surface.DrawCircle((long)((x2-x_min)*xscale+rc.left+BORDER_X), (long)((y_max-y2)*yscale+rc.top), (long)(aatradius[i]*yscale), true); } } } } if (!AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; if (!ValidTaskPoint(1) ) { lat2 = GPS_INFO.Latitude; lon2 = GPS_INFO.Longitude; } else { lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].Longitude; } x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); x2 = (lon2-lon_c)*fastcosine(lat2); y2 = (lat2-lat_c); // DrawLine(hdc, rc, x1, y1, x2, y2, STYLE_DASHGREEN); if( ValidTaskPoint(4) && i <2) goto skip_FAI; #ifndef UNDITHER RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN ); #else RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY ); #endif skip_FAI: DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_DASHGREEN); Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc, Task[i].AATStartRadial, Task[i].AATFinishRadial); } } if( ValidTaskPoint(1) && ValidTaskPoint(3)) { lat1 = WayPointList[Task[3].Index].Latitude; lon1 = WayPointList[Task[3].Index].Longitude; lat2 = WayPointList[Task[1].Index].Latitude; lon2 = WayPointList[Task[1].Index].Longitude; #ifndef UNDITHER RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN ); #else RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY ); RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY ); #endif } } // draw task lines and label for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; if (!ValidTaskPoint(1) ) { lat2 = GPS_INFO.Latitude; lon2 = GPS_INFO.Longitude; } else { lat2 = WayPointList[Task[i].Index].Latitude; lon2 = WayPointList[Task[i].Index].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_BLUETHIN); #if (WINDOWSPC>0) Surface.SetBackgroundOpaque(); #endif TCHAR text[100]; Surface.SetTextColor(RGB_BLUE); /* if ((i==nwps-1) && (Task[i].Index == Task[0].Index)) { _stprintf(text,TEXT("%0d"),1); DrawLabel(hdc, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2); } else */ { _stprintf(text,TEXT("%0d"),i); DrawLabel(Surface, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2); } if ((i==ActiveTaskPoint)&&(!AATEnabled)) { lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_REDTHICK); } } } // draw aat task line if (AATEnabled) { for (i=MAXTASKPOINTS-1; i>0; i--) { if (ValidTaskPoint(i) && ValidTaskPoint(i-1)) { if (i==1) { lat1 = WayPointList[Task[i-1].Index].Latitude; lon1 = WayPointList[Task[i-1].Index].Longitude; } else { lat1 = Task[i-1].AATTargetLat; lon1 = Task[i-1].AATTargetLon; } lat2 = Task[i].AATTargetLat; lon2 = Task[i].AATTargetLon; 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_REDTHICK); } } } DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false); Surface.SelectObject(hfOldU); // Draw aircraft on top lat1 = GPS_INFO.Latitude; lon1 = GPS_INFO.Longitude; x1 = (lon1-lon_c)*fastcosine(lat1); y1 = (lat1-lat_c); Surface.SetBackgroundTransparent(); DrawLabel(Surface, rc, TEXT("+"), x1, y1); }
void Statistics::RenderSpeed(LKSurface& Surface, const RECT& rc) { if ((flightstats.Task_Speed.sum_n<2) || !ValidTaskPoint(ActiveTaskPoint)) { DrawNoData(Surface, rc); return; } ResetScale(); ScaleXFromData(rc, &flightstats.Task_Speed); ScaleYFromData(rc, &flightstats.Task_Speed); ScaleYFromValue(rc, 0); ScaleXFromValue(rc, flightstats.Task_Speed.x_min+1.0); // in case no data ScaleXFromValue(rc, flightstats.Task_Speed.x_min); for(int j=1;j<MAXTASKPOINTS;j++) { if (ValidTaskPoint(j) && (flightstats.LegStartTime[j]>=0)) { double xx = (flightstats.LegStartTime[j]-CALCULATED_INFO.TaskStartTime)/3600.0; if (xx>=0) { DrawLine(Surface, rc, xx, y_min, xx, y_max, STYLE_REDTHICK); } } } DrawXGrid(Surface, rc, 0.5, flightstats.Task_Speed.x_min, STYLE_THINDASHPAPER, 0.5, true); /* DrawYGrid(hdc, rc, 10/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 10, true);*/ if(Units::GetUserHorizontalSpeedUnit() == unStatuteMilesPerHour) { DrawYGrid(Surface, rc, 5.0/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 5.0, true); } else { DrawYGrid(Surface, rc, 10/TASKSPEEDMODIFY, 0, STYLE_THINDASHPAPER, 10, true); } DrawLineGraph(Surface, rc, &flightstats.Task_Speed,STYLE_MEDIUMBLACK); DrawTrend(Surface, rc, &flightstats.Task_Speed, STYLE_BLUETHIN); if(INVERTCOLORS || IsDithered()) Surface.SetTextColor(RGB_DARKGREEN); else Surface.SetTextColor(RGB_GREEN); Surface.SetBackgroundOpaque(); TCHAR text[80]; DrawXLabel(Surface, rc, TEXT(" t/h ")); _stprintf(text,TEXT(" v/%s "),Units::GetHorizontalSpeedName()); DrawYLabel(Surface, rc, text); // DrawXLabel(hdc, rc, TEXT("t")); // DrawYLabel(hdc, rc, TEXT("V")); }
void Statistics::RenderTemperature(LKSurface& Surface, const RECT& rc) { ResetScale(); int i; float hmin= 10000; float hmax= -10000; float tmin= (float)CuSonde::maxGroundTemperature; float tmax= (float)CuSonde::maxGroundTemperature; // find range for scaling of graph for (i=0; i<CUSONDE_NUMLEVELS-1; i++) { if (CuSonde::cslevels[i].nmeasurements) { hmin = min(hmin, (float)i); hmax = max(hmax, (float)i); tmin = min(tmin, (float)min(CuSonde::cslevels[i].tempDry, (double)min(CuSonde::cslevels[i].airTemp, (double)CuSonde::cslevels[i].dewpoint))); tmax = max(tmax, (float)max(CuSonde::cslevels[i].tempDry, (double)max(CuSonde::cslevels[i].airTemp, (double)CuSonde::cslevels[i].dewpoint))); } } if (hmin>= hmax) { DrawNoData(Surface, rc); return; } ScaleYFromValue(rc, hmin); ScaleYFromValue(rc, hmax); ScaleXFromValue(rc, tmin); ScaleXFromValue(rc, tmax); bool labelDry = false; bool labelAir = false; bool labelDew = false; int ipos = 0; for (i=0; i<CUSONDE_NUMLEVELS-1; i++) { if (CuSonde::cslevels[i].nmeasurements && CuSonde::cslevels[i+1].nmeasurements) { ipos++; DrawLine(Surface, rc, CuSonde::cslevels[i].tempDry, i, CuSonde::cslevels[i+1].tempDry, (i+1), STYLE_REDTHICK); DrawLine(Surface, rc, CuSonde::cslevels[i].airTemp, i, CuSonde::cslevels[i+1].airTemp, (i+1), STYLE_MEDIUMBLACK); DrawLine(Surface, rc, CuSonde::cslevels[i].dewpoint, i, CuSonde::cslevels[i+1].dewpoint, i+1, STYLE_BLUETHIN); if (ipos> 2) { if (!labelDry) { DrawLabel(Surface, rc, TEXT("DALR"), CuSonde::cslevels[i+1].tempDry, i); labelDry = true; } else { if (!labelAir) { DrawLabel(Surface, rc, TEXT("Air"), CuSonde::cslevels[i+1].airTemp, i); labelAir = true; } else { if (!labelDew) { DrawLabel(Surface, rc, TEXT("Dew"), CuSonde::cslevels[i+1].dewpoint, i); labelDew = true; } } } } } } if(INVERTCOLORS) Surface.SetTextColor(RGB_DARKGREEN); else Surface.SetTextColor(RGB_GREEN); #if (WINDOWSPC>0) Surface.SetBackgroundOpaque(); #endif TCHAR text[80]; _stprintf(text,TEXT(" T/%sC "), gettext(_T("_@M2179_"))); DrawXLabel(Surface, rc, text); _stprintf(text,TEXT(" h/%s "),Units::GetAltitudeName()); DrawYLabel(Surface, rc, text); // DrawXLabel(hdc, rc, TEXT("T")TEXT(DEG)); // DrawYLabel(hdc, rc, TEXT("h")); }
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 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(); } } } }
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()*/); }