// // Paint a circle around thermal multitarget // Called only during map mode L> // void MapWindow::DrawThermalEstimateMultitarget(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj) { int idx=0; // do not mix old and new thermals if (mode.Is(Mode::MODE_CIRCLING)) return; // draw only when visible , at high zoom level if ( MapWindow::zoom.RealScale() >1 ) return; idx=GetThermalMultitarget(); // no L> target destination if (idx <0) return; const POINT screen = _Proj.LonLat2Screen( ThermalHistory[idx].Longitude, ThermalHistory[idx].Latitude); double tradius; if (ISPARAGLIDER) tradius=100; else tradius=200; const auto oldPen = Surface.SelectObject(LKPen_White_N3); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify()), rc, false); Surface.SelectObject(LKPen_White_N2); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify())+NIBLSCALE(2), rc, false); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify()), rc, false); Surface.SelectObject(oldPen); }
void Statistics::DrawBarChart(LKSurface& Surface, const RECT& rc, LeastSquares* lsdata) { int i; LKColor Col; if (unscaled_x || unscaled_y) { return; } if(INVERTCOLORS) Col = RGB_GREEN.ChangeBrightness(0.5); else Col = RGB_WHITE; LKPen hpBar(PEN_SOLID, IBLSCALE(1), Col); LKBrush hbBar(Col); const auto oldpen = Surface.SelectObject(hpBar); const auto oldbrush = Surface.SelectObject(hbBar); int xmin, ymin, xmax, ymax; for (i= 0; i<lsdata->sum_n; i++) { xmin = (int)((i+1+0.2)*xscale)+rc.left+BORDER_X; ymin = (int)((y_max-y_min)*yscale)+rc.top; xmax = (int)((i+1+0.8)*xscale)+rc.left+BORDER_X; ymax = (int)((y_max-lsdata->ystore[i])*yscale)+rc.top; Surface.Rectangle(xmin, ymin, xmax, ymax); } Surface.SelectObject(oldpen); Surface.SelectObject(oldbrush); }
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); } } }
// // Draw circles and gadgets for thermals // void MapWindow::DrawThermalEstimate(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj) { if (!EnableThermalLocator) return; if (mode.Is(Mode::MODE_CIRCLING)) { if (DerivedDrawInfo.ThermalEstimate_R>0) { const POINT screen = _Proj.LonLat2Screen(DerivedDrawInfo.ThermalEstimate_Longitude, DerivedDrawInfo.ThermalEstimate_Latitude); DrawBitmapIn(Surface, screen, hBmpThermalSource); const auto oldBrush = Surface.SelectObject(LKBrush_Hollow); double tradius; if (ISPARAGLIDER) tradius=50; else tradius=100; const auto oldPen = Surface.SelectObject(LKPen_White_N3); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify()), rc, true); Surface.SelectObject(LKPen_Black_N1); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify())+NIBLSCALE(2), rc, true); Surface.DrawCircle(screen.x, screen.y, (int)(tradius*zoom.ResScaleOverDistanceModify()), rc, true); Surface.SelectObject(oldPen); Surface.SelectObject(oldBrush); } } else { if (zoom.RealScale() <= 4) { for (int i=0; i<MAX_THERMAL_SOURCES; i++) { if (DerivedDrawInfo.ThermalSources[i].Visible) { DrawBitmapIn(Surface, DerivedDrawInfo.ThermalSources[i].Screen, hBmpThermalSource); } } } } }
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); } } } }
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); }
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); } }
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); }
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); } }
// // Draw bearing line to target // void MapWindow::DrawGreatCircle(LKSurface& Surface, double startLon, double startLat, double targetLon, double targetLat, const RECT& rc) { POINT pt[2]; LatLon2Screen(startLon, startLat, pt[0]); LatLon2Screen(targetLon, targetLat, pt[1]); if(LKGeom::ClipLine(rc, pt[0], pt[1])) { const auto hpOld = Surface.SelectObject(LKPen_GABRG); Surface.Polyline(pt, 2); Surface.SelectObject(LK_BLACK_PEN); Surface.Polyline(pt, 2); Surface.SelectObject(hpOld); } }
// // Draw bearing line to target // void MapWindow::DrawGreatCircle(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj, double startLon, double startLat, double targetLon, double targetLat) { POINT pt[2] = { _Proj.LonLat2Screen(startLon, startLat), _Proj.LonLat2Screen(targetLon, targetLat) }; if(LKGeom::ClipLine(rc, pt[0], pt[1])) { const auto hpOld = Surface.SelectObject(LKPen_GABRG); Surface.Polyline(pt, 2); Surface.SelectObject(LK_BLACK_PEN); Surface.Polyline(pt, 2); Surface.SelectObject(hpOld); } }
void MapWindow::DrawBestCruiseTrack(LKSurface& Surface, const POINT& Orig) { if (OvertargetMode>OVT_TASK) return; if (!ValidTaskPoint(ActiveTaskPoint)) return; if (DerivedDrawInfo.WaypointDistance < 0.010) return; // dont draw bestcruise indicator if not needed if (fabs(DerivedDrawInfo.BestCruiseTrack-DerivedDrawInfo.WaypointBearing)<2) { // 091202 10 to 2 return; } const auto hpOld = Surface.SelectObject(LKPen_Blue_N1); const auto hbOld = Surface.SelectObject(LKBrush_Blue); if (Appearance.BestCruiseTrack == ctBestCruiseTrackDefault){ int dy = (long)(70); POINT Arrow[7] = { {-1,-40}, {1,-40}, {1,0}, {6,8}, {-6,8}, {-1,0}, {-1,-40}}; Arrow[2].y -= dy; Arrow[3].y -= dy; Arrow[4].y -= dy; Arrow[5].y -= dy; PolygonRotateShift(Arrow, 7, Orig.x, Orig.y, DerivedDrawInfo.BestCruiseTrack-DisplayAngle); Surface.Polygon(Arrow,7); } else if (Appearance.BestCruiseTrack == ctBestCruiseTrackAltA){ POINT Arrow[] = { {-1,-40}, {-1,-62}, {-6,-62}, {0,-70}, {6,-62}, {1,-62}, {1,-40}, {-1,-40}}; PolygonRotateShift(Arrow, sizeof(Arrow)/sizeof(Arrow[0]), Orig.x, Orig.y, DerivedDrawInfo.BestCruiseTrack-DisplayAngle); Surface.Polygon(Arrow, (sizeof(Arrow)/sizeof(Arrow[0]))); } Surface.SelectObject(hpOld); Surface.SelectObject(hbOld); }
void MapWindow::DrawAirSpaceBorders(LKSurface& Surface, const RECT& rc) { CAirspaceList::const_iterator it; const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetNearAirspacesRef(); int airspace_type; static bool asp_selected_flash = false; asp_selected_flash = !asp_selected_flash; LKBrush oldBrush = Surface.SelectObject(LKBrush_Hollow); CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef()); // for (it=airspaces_to_draw.end(); it != airspaces_to_draw.begin(); it--) /*********************************************************************** * draw underlying aispaces first (reverse order) with bigger pen * *********************************************************************/ it=airspaces_to_draw.end(); if (it!=airspaces_to_draw.begin()) do { it--; if ((*it)->DrawStyle()) { airspace_type = (*it)->Type(); if ( asp_selected_flash && (*it)->Selected() ) { Surface.SelectObject(LK_BLACK_PEN); } else { Surface.SelectObject(hBigAirspacePens[airspace_type]); } if((*it)->DrawStyle()==adsDisabled) Surface.SelectObject(LKPen_Grey_N2 ); (*it)->Draw(Surface, rc, false); } } while (it !=airspaces_to_draw.begin()); /*********************************************************************** * now draw aispaces on top (normal order) with thin pen ***********************************************************************/ for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) { if ((*it)->DrawStyle()) { airspace_type = (*it)->Type(); if ( asp_selected_flash && (*it)->Selected() ) { Surface.SelectObject(LK_BLACK_PEN); } else { Surface.SelectObject(hAirspacePens[airspace_type]); } if((*it)->DrawStyle()==adsDisabled) Surface.SelectObject(LKPen_Black_N0 ); (*it)->Draw(Surface, rc, false); } }//for Surface.SelectObject(oldBrush); }
void MapWindow::LKDrawLongTrail( LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj) { static RasterPoint snail_polyline[array_size(LongSnailTrail)+1]; // +1 for last point of "normal" snail trail if (TrailActive != 3) return; // only when full trail is selected if (iLongSnailNext < 2) return; // no reason to draw a single point if (MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING)) { return; } // pixel manhattan distance // It is the sum of x and y differences between previous and next point on screen, in pixels. // below this distance, no painting const unsigned nearby=10; const LONG_SNAIL_POINT* end_iterator = std::begin(LongSnailTrail); const LONG_SNAIL_POINT* cur_iterator = std::prev(std::next(LongSnailTrail,iLongSnailNext)); RasterPoint* polyline_iterator = std::begin(snail_polyline); const SNAIL_POINT* last_point = std::next(std::next(SnailTrail, iSnailNext)); if(last_point == std::end(SnailTrail)) { last_point = std::begin(SnailTrail); } (*polyline_iterator) = _Proj.LonLat2Screen(last_point->Longitude, last_point->Latitude); polyline_iterator = std::next(polyline_iterator); const auto oldPen = Surface.SelectObject(hSnailPens[3]); // blue color while(cur_iterator != end_iterator) { (*polyline_iterator) = _Proj.LonLat2Screen(cur_iterator->Longitude, cur_iterator->Latitude); if(manhattan_distance(*std::prev(polyline_iterator),(*polyline_iterator)) > nearby) { polyline_iterator = std::next(polyline_iterator); } cur_iterator = std::prev(cur_iterator); } Surface.Polyline(snail_polyline, std::distance(snail_polyline, polyline_iterator) , rc); Surface.SelectObject(oldPen); }
void MapWindow::DrawStartEndSector(LKSurface& Surface, const RECT& rc, const POINT &Start, const POINT &End, int Index, int Type, double Radius) { double tmp; LKSurface::OldPen oldpen; LKSurface::OldBrush oldbrush; switch (Type) { case 0: // CIRCLE tmp = Radius * zoom.ResScaleOverDistanceModify(); oldpen = Surface.SelectObject(hpStartFinishThick); oldbrush = Surface.SelectObject(LKBrush_Hollow); Surface.Circle(WayPointList[Index].Screen.x, WayPointList[Index].Screen.y, (int) tmp, rc, false, false); Surface.SelectObject(LKPen_Red_N1); Surface.Circle(WayPointList[Index].Screen.x, WayPointList[Index].Screen.y, (int) tmp, rc, false, false); Surface.SelectObject(oldpen); Surface.SelectObject(oldbrush); break; case 1: // LINE Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), End, Start, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), End, Start, LKColor(255, 0, 0), rc); break; case 2: // SECTOR Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), WayPointList[Index].Screen, Start, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), WayPointList[Index].Screen, End, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), WayPointList[Index].Screen, Start, LKColor(255, 0, 0), rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), WayPointList[Index].Screen, End, LKColor(255, 0, 0), rc); break; } }
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(); }
// // Like DrawDashLine, but with two alternating colors // void MapWindow::DrawMulticolorDashLine(LKSurface& Surface, const int width, const POINT& ptStart, const POINT& ptEnd, const LKColor& cr1, const LKColor& cr2, const RECT& rc) { int i; POINT pt[2]; bool flipcol=false; #ifdef GTL2 int Offset = ((width - 1) / 2) + 1; // amount to shift 1st line to center // the group of lines properly #endif //Create a dot pen LKPen hpDash1(PEN_DASH, 1, cr1); LKPen hpDash2(PEN_DASH, 1, cr2); const auto hpOld = Surface.SelectObject(hpDash1); #ifdef GTL2 pt[0] = ptStart; pt[1] = ptEnd; #else pt[0].x = ptStart.x; pt[0].y = ptStart.y; pt[1].x = ptEnd.x; pt[1].y = ptEnd.y; #endif //increment on smallest variance if(abs(ptStart.x - ptEnd.x) < abs(ptStart.y - ptEnd.y)){ #ifdef GTL2 pt[0].x -= Offset; pt[1].x -= Offset; #endif for (i = 0; i < width; i++, flipcol=!flipcol){ flipcol ? Surface.SelectObject(hpDash2) : Surface.SelectObject(hpDash1); pt[0].x += 1; pt[1].x += 1; Surface.Polyline(pt, 2, rc); } } else { #ifdef GTL2 pt[0].y -= Offset; pt[1].y -= Offset; #endif for (i = 0; i < width; i++, flipcol=!flipcol){ flipcol ? Surface.SelectObject(hpDash2) : Surface.SelectObject(hpDash1); pt[0].y += 1; pt[1].y += 1; Surface.Polyline(pt, 2, rc); } } Surface.SelectObject(hpOld); }
void MapWindow::DrawAirSpaceBorders(LKSurface& Surface, const RECT& rc) { static bool asp_selected_flash = false; asp_selected_flash = !asp_selected_flash; const auto oldBrush = Surface.SelectObject(LKBrush_Hollow); ScopeLock guard(CAirspaceManager::Instance().MutexRef()); const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetNearAirspacesRef(); /*********************************************************************** * draw underlying aispaces first (reverse order) with bigger pen * *********************************************************************/ for (CAirspaceList::const_reverse_iterator it=airspaces_to_draw.rbegin(); it != airspaces_to_draw.rend(); ++it) { if ((*it)->DrawStyle()) { if ( asp_selected_flash && (*it)->Selected() ) { Surface.SelectObject(LK_BLACK_PEN); } else { Surface.SelectObject(hBigAirspacePens[(*it)->Type()]); } if((*it)->DrawStyle()==adsDisabled) { Surface.SelectObject(LKPen_Grey_N2 ); } (*it)->Draw(Surface, false); } } // for /*********************************************************************** * now draw airspaces on top (normal order) with thin pen ***********************************************************************/ for (CAirspaceList::const_iterator it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) { if ((*it)->DrawStyle()) { if ( asp_selected_flash && (*it)->Selected() ) { Surface.SelectObject(LK_BLACK_PEN); } else { Surface.SelectObject(hAirspacePens[(*it)->Type()]); } if((*it)->DrawStyle() != adsDisabled) (*it)->Draw(Surface, false); } }//for Surface.SelectObject(oldBrush); }
static void OnProgressPaint(WindowControl * Sender, LKSurface& Surface) { RECT PrintAreaR = Sender->GetClientRect(); const auto oldFont = Surface.SelectObject(MapWindowBoldFont); Surface.FillRect(&PrintAreaR, LKBrush_Petrol); // Create text area // we cannot use LKPen here because they are not still initialised for startup menu. no problem LKPen hP(PEN_SOLID,NIBLSCALE(1),RGB_GREEN); auto ohP = Surface.SelectObject(hP); const auto ohB = Surface.SelectObject(LKBrush_Petrol); Surface.Rectangle(PrintAreaR.left,PrintAreaR.top,PrintAreaR.right,PrintAreaR.bottom); Surface.SelectObject(ohP); hP.Release(); hP.Create(PEN_SOLID,NIBLSCALE(1),RGB_BLACK); ohP = Surface.SelectObject(hP); Surface.SelectObject(LK_HOLLOW_BRUSH); InflateRect(&PrintAreaR, -NIBLSCALE(2), -NIBLSCALE(2)); Surface.Rectangle(PrintAreaR.left,PrintAreaR.top,PrintAreaR.right,PrintAreaR.bottom); Surface.SetTextColor(RGB_WHITE); Surface.SetBackgroundTransparent(); InflateRect(&PrintAreaR, -NIBLSCALE(2), -NIBLSCALE(2)); const TCHAR* text = Sender->GetCaption(); Surface.DrawText(text, &PrintAreaR, DT_VCENTER|DT_SINGLELINE); Surface.SelectObject(ohB); Surface.SelectObject(ohP); Surface.SelectObject(oldFont); }
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::DrawGlideThroughTerrain(LKSurface& Surface, const RECT& rc) { LKPen hpOld; //double h,dh; TCHAR hbuf[10]; static bool doinit=true; static TextInBoxMode_t tmode = {0}; bool wrotevalue=false; if (doinit) { memset((void*)&tmode, 0, sizeof(TextInBoxMode_t)); tmode.Border=1; doinit=false; } #ifdef GTL2 bool ValidTP = ValidTaskPoint(ActiveWayPoint); // draw glide terrain line around next WP bool DrawGTL2 = ValidTP && (FinalGlideTerrain > 2); static bool LastDrewGTL2 = false; if (DrawGTL2) { int wp_index = (DoOptimizeRoute() || ACTIVE_WP_IS_AAT_AREA) ? RESWP_OPTIMIZED : TASKINDEX; double alt_arriv = WayPointCalc[wp_index].AltArriv[AltArrivMode]; // Calculate arrival altitude at the next waypoint relative to // the "terrain height" safety setting. if (CheckSafetyAltitudeApplies(wp_index)) alt_arriv += SAFETYALTITUDEARRIVAL/10; // AGL alt_arriv -= SAFETYALTITUDETERRAIN/10; // rel. to "terrain height" if (alt_arriv <= 0) DrawGTL2 = false; } if (LastDrewGTL2 != DrawGTL2) { LastDrewGTL2 = DrawGTL2; if (!DrawGTL2) ClearGTL2(); // clear next-WP glide terrain line } #endif hpOld = Surface.SelectObject(hpTerrainLineBg); #ifdef GTL2 // Draw the wide, solid part of the glide terrain line. #else // draw a dashed perimetral line first #endif Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); // draw perimeter if selected and during a flight #ifdef GTL2 if (((FinalGlideTerrain == 1) || (FinalGlideTerrain == 3)) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && FinalGlideTerrain)) { #else if ((FinalGlideTerrain==1) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && (FinalGlideTerrain==2))) { #endif Surface.SelectObject(hpTerrainLine); Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); } #ifdef GTL2 // draw glide terrain line around next waypoint if (DrawGTL2) { // Draw a solid white line. Surface.SelectObject(LKPen_White_N2); Surface.Polyline(Groundline2, NUMTERRAINSWEEPS+1, rc); // Draw a dashed red line. Surface.DrawDashPoly(NIBLSCALE(2), RGB_RED, Groundline2, NUMTERRAINSWEEPS+1, rc); } #endif // draw red cross obstacles only if destination looks reachable! // only if using OVT_TASK of course! #ifdef GTL2 if ((OvertargetMode == OVT_TASK) && DerivedDrawInfo.Flying && ValidTP) #else if ( (OvertargetMode==OVT_TASK) && DerivedDrawInfo.Flying && ValidTaskPoint(ActiveWayPoint)) #endif if (WayPointCalc[TASKINDEX].AltArriv[AltArrivMode] >0) { POINT sc; // If calculations detected an obstacle... if ((DerivedDrawInfo.TerrainWarningLatitude != 0.0) &&(DerivedDrawInfo.TerrainWarningLongitude != 0.0)) { // only if valid position, and visible if (DerivedDrawInfo.FarObstacle_Lon >0) if (PointVisible(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat)) { LatLon2Screen(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); if (DerivedDrawInfo.FarObstacle_AltArriv <=-50 || DerivedDrawInfo.FarObstacle_Dist<5000 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.FarObstacle_AltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); wrotevalue=true; } } // visible far obstacle if (PointVisible(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude)) { LatLon2Screen(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); #if 0 // 091203 add obstacle altitude on moving map h = max(0,RasterTerrain::GetTerrainHeight(DerivedDrawInfo.TerrainWarningLatitude, DerivedDrawInfo.TerrainWarningLongitude)); if (h==TERRAIN_INVALID) h=0; //@ 101027 FIX but unused dh = CALCULATED_INFO.NavAltitude - h - (SAFETYALTITUDETERRAIN/10); _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*dh); TextInBox(hDC,&rc,hbuf,sc.x+NIBLSCALE(10), sc.y, 0, tmode,false); #else // if far obstacle was painted with value... if (wrotevalue) { // if it is not too near the nearest.. if ( (fabs(DerivedDrawInfo.FarObstacle_Lon - DerivedDrawInfo.TerrainWarningLongitude) >0.02) && (fabs(DerivedDrawInfo.FarObstacle_Lat - DerivedDrawInfo.TerrainWarningLatitude) >0.02)) { // and it the arrival altitude is actually negative (rounding terrain errors?) if ( DerivedDrawInfo.ObstacleAltArriv <=-50) // and there is a significant difference in the numbers, then paint value also for nearest if ( fabs(DerivedDrawInfo.ObstacleAltArriv - DerivedDrawInfo.FarObstacle_AltArriv) >100 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } } else { // else paint value only if meaningful or very close to us // -1 to 10m become -1 for rounding errors if ( (DerivedDrawInfo.ObstacleAltArriv >-1) && (DerivedDrawInfo.ObstacleAltArriv <10)) DerivedDrawInfo.ObstacleAltArriv=-1; if (DerivedDrawInfo.ObstacleAltArriv <=-50 || ((DerivedDrawInfo.ObstacleAltArriv<0) && (DerivedDrawInfo.ObstacleDistance<5000)) ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } #endif } // visible nearest obstacle } // obstacles detected } // within glide range Surface.SelectObject(hpOld); }
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); }
int MapWindow::SharedTopView(LKSurface& Surface, DiagrammStruct* psDia , double fAS_Bearing, double fWP_Bearing) { int iOldDisplayOrientation = DisplayOrientation; DiagrammStruct m_Dia = *psDia; const RECT& rct = m_Dia.rc; unsigned short getsideviewpage=GetSideviewPage(); LKASSERT(getsideviewpage<NUMBER_OF_SHARED_MULTIMAPS); LKASSERT(Current_Multimap_SizeY!=SIZE0); DisplayOrientation = GetMMNorthUp(getsideviewpage); switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: break; case NORTHUP: default: m_Dia.fXMin = -m_Dia.fXMax; break; } double fOldScale = zoom.Scale(); const auto hfOld = Surface.SelectObject(LK8PanelUnitFont); if(zoom.AutoZoom()) zoom.AutoZoom(false); double fFact = 1.25 ; #ifdef INIT_CASE switch(ScreenSize) { case ss800x480: fFact=0.750; break; case ss640x480: fFact=0.938; break; case ss480x272: fFact=0.708; break; case ss400x240: fFact=0.750; break; case ss320x240: fFact=0.938; break; case ss480x800: fFact=1.250; break; case ss480x640: fFact=1.250; break; case ss272x480: fFact=1.250; break; case ss240x400: fFact=1.250; break; case ss240x320: fFact=1.250; break; default: fFact=1.000; break; } #endif if((ScreenSizeX > 0) && (ScreenSizeY > 0)) { if(ScreenSizeX > ScreenSizeY) fFact = (double)ScreenSizeY/(double)ScreenSizeX * 1.250; } PanLatitude = DrawInfo.Latitude; PanLongitude = DrawInfo.Longitude; switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: DisplayAngle = AngleLimit360(fAS_Bearing +270.0); DisplayAircraftAngle = AngleLimit360(fWP_Bearing); break; case NORTHUP: default: DisplayAngle = 0; if( getsideviewpage == IM_HEADING || getsideviewpage==IM_VISUALGLIDE) DisplayAircraftAngle = AngleLimit360(fAS_Bearing); else DisplayAircraftAngle = AngleLimit360(DrawInfo.TrackBearing); break; } int iOldLocator = EnableThermalLocator; EnableThermalLocator =0; /*******/ #warning "wrong place for do that, always bad idea to change layout inside drawing fonctions !" MapWindow::ChangeDrawRect(rct); // set new area for terrain and topology /*******/ zoom.RequestedScale((m_Dia.fXMax -m_Dia.fXMin) * fFact * (DISTANCEMODIFY)/10.0f); POINT Orig = { CalcDistanceCoordinat(0.0, (DiagrammStruct*) &m_Dia),(rct.bottom-rct.top)/2}; POINT Orig_Aircraft= {0,0}; zoom.ModifyMapScale(); zoom.UpdateMapScale(); const ScreenProjection _Proj = CalculateScreenPositions( Orig, rct, &Orig_Aircraft); CalculateScreenPositionsAirspace(rct, _Proj); bool terrainpainted=false; if (IsMultimapTerrain() && DerivedDrawInfo.TerrainValid && RasterTerrain::isTerrainLoaded() ) { LKTextBlack=false; BlackScreen=false; LockTerrainDataGraphics(); DrawTerrain(Surface, rct, _Proj, GetAzimuth(), 40.0); UnlockTerrainDataGraphics(); terrainpainted=true; } else { // We fill up the background wity chosen empty map color Surface.FillRect(&rct, hInvBackgroundBrush[BgMapColor]); // We force LK painting black values on screen depending on the background color in use // blackscreen would force everything to be painted white, instead LKTextBlack=BgMapColorTextBlack[BgMapColor]; if (BgMapColor>6 ) BlackScreen=true; else BlackScreen=false; } ResetLabelDeclutter(); // We reduce screen cluttering for some cases.. short olddecluttermode=DeclutterMode; if (Current_Multimap_SizeY==SIZE4) goto _nomoredeclutter; if (Current_Multimap_SizeY<SIZE3) { DeclutterMode+=2; } else { if (Current_Multimap_SizeY==SIZE3) DeclutterMode++; } if (DeclutterMode>dmVeryHigh) DeclutterMode=dmVeryHigh; _nomoredeclutter: if (IsMultimapTopology()) { // Do not print topology labels, to be used with another config later! // SaturateLabelDeclutter(); DrawTopology(Surface, rct, _Proj); } else { // No topology is desired, but terrain requires water areas nevertheless if (terrainpainted) { DrawTopology(Surface, rct, _Proj, true); // water only! } } if (IsMultimapAirspace()) { DrawAirSpace(Surface, rct, _Proj); // full screen, to hide clipping effect on low border } if (Flags_DrawTask && MapSpaceMode!=MSM_MAPASP && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskAAT(Surface, rct); DrawTask(Surface, rct, _Proj, Orig_Aircraft); } if (IsMultimapWaypoints()) { DrawWaypointsNew(Surface,rct); } if (Flags_DrawFAI) DrawFAIOptimizer(Surface, rct, _Proj, Orig_Aircraft); DeclutterMode=olddecluttermode; // set it back correctly /* THIS STUFF DOES NOT WORK IN SHARED MAPS, YET NEED FIXING LatLon2Screen for shared maps using Sideview #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) DrawTerrainAbove(hdc, rct); #endif */ // // Stuff for MAPTRK only (M1) if (MapSpaceMode==MSM_MAPTRK) { if(IsMultimapTerrain() || IsMultimapTopology() ) { if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) DrawGlideThroughTerrain(Surface, rct, _Proj); } if (extGPSCONNECT) DrawBearing(Surface, rct, _Proj); // Wind arrow if (IsMultimapOverlaysGauges()) DrawWindAtAircraft2(Surface, Orig_Aircraft, rct); } if (MapSpaceMode==MSM_MAPWPT) { if (extGPSCONNECT) DrawBearing(Surface, rct, _Proj); } switch(GetMMNorthUp(getsideviewpage)) { case NORTHUP: default: DrawCompass( Surface, rct, 0); break; case TRACKUP: if(getsideviewpage == IM_HEADING || getsideviewpage == IM_VISUALGLIDE) DrawCompass( Surface, rct, DrawInfo.TrackBearing-90.0); else DrawCompass( Surface, rct, DisplayAngle); break; } /**************************************************************************************************** * draw vertical line ****************************************************************************************************/ POINT line[2]; line[0].x = rct.left; line[0].y = Orig_Aircraft.y-1; line[1].x = rct.right; line[1].y = line[0].y; switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: // Are we are not topview fullscreen? if (Current_Multimap_SizeY<SIZE4 && !(MapSpaceMode==MSM_VISUALGLIDE)) { Surface.DrawDashLine(NIBLSCALE(1), line[0], line[1], Sideview_TextColor, rct); } else { if (TrackBar) { DrawHeadUpLine(Surface, Orig, rct, psDia->fXMin ,psDia->fXMax); if (ISGAAIRCRAFT) DrawFuturePos(Surface, Orig, rct, true); } } break; case NORTHUP: default: if (TrackBar) { DrawHeadUpLine(Surface, Orig, rct, psDia->fXMin ,psDia->fXMax); if (ISGAAIRCRAFT) DrawFuturePos(Surface, Orig, rct, true); } break; } DrawAircraft(Surface, Orig_Aircraft); // M3 has sideview always on, so wont apply here, and no need to check if (Current_Multimap_SizeY==SIZE4) { DrawMapScale(Surface,rct,0); } MapWindow::zoom.RequestedScale(fOldScale); EnableThermalLocator = iOldLocator; DisplayOrientation = iOldDisplayOrientation; Surface.SelectObject(hfOld); return 0; }
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 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; }
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 MapWindow::LKDrawTrail(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj) { static RasterPoint snail_polyline[array_size(SnailTrail)]; if (!TrailActive) return; const double display_time = DrawInfo.Time; const bool use_colors = (MapWindow::zoom.RealScale() < 2); // 1.5 is also quite good; // Trail size int num_trail_max = TRAILSIZE; if (TrailActive == 2) { // scan only recently for lift magnitude (10 min) num_trail_max /= TRAILSHRINK; } if (MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING)) { num_trail_max /= TRAILSHRINK; // ( 2 min for short track ? ) } const SNAIL_POINT* end_iterator = std::next(SnailTrail,iSnailNext); const SNAIL_POINT* cur_iterator = end_iterator; if(cur_iterator != std::begin(SnailTrail)) { cur_iterator = std::prev(cur_iterator); } else { cur_iterator = std::prev(std::end(SnailTrail)); } RasterPoint* polyline_iterator = &snail_polyline[0]; unsigned short prev_color = 2; if(use_colors) { prev_color = cur_iterator->Colour; } Surface.SelectObject(hSnailPens[prev_color]); const bool trail_is_drifted = (EnableTrailDrift && MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING) && DerivedDrawInfo.WindSpeed >= 1); double traildrift_lat = 0; double traildrift_lon = 0; if(trail_is_drifted) { double tlat1, tlon1; FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, DerivedDrawInfo.WindBearing, DerivedDrawInfo.WindSpeed, &tlat1, &tlon1); traildrift_lat = (DrawInfo.Latitude - tlat1); traildrift_lon = (DrawInfo.Longitude - tlon1); } while( (num_trail_max--) > 0 && cur_iterator->Time && cur_iterator != end_iterator) { double this_lat = cur_iterator->Latitude; double this_lon = cur_iterator->Longitude; if (trail_is_drifted) { double dt = std::max(0.0, (display_time - cur_iterator->Time) * cur_iterator->DriftFactor); this_lat += traildrift_lat * dt; this_lon += traildrift_lon * dt; } (*polyline_iterator) = _Proj.LonLat2Screen(this_lon, this_lat); if(use_colors && prev_color != cur_iterator->Colour) { // draw polyline before change color. Surface.Polyline(snail_polyline, std::distance(snail_polyline, polyline_iterator)+1 , rc); // reset polyline snail_polyline[0] = *polyline_iterator; polyline_iterator = &snail_polyline[1]; // select new Color prev_color = cur_iterator->Colour; Surface.SelectObject(hSnailPens[prev_color]); } else { polyline_iterator = std::next(polyline_iterator); } if(cur_iterator == std::begin(SnailTrail)) { cur_iterator = std::end(SnailTrail); } cur_iterator = std::prev(cur_iterator); } Surface.Polyline(snail_polyline, std::distance(snail_polyline, polyline_iterator) , rc); }
void Topology::Paint(LKSurface& Surface, const RECT& rc) { if (!shapefileopen) return; bool nolabels=false; // 130217 scaleCat 5 and 10 are the same! So careful.. if (scaleCategory==10||scaleCategory==5) { // for water areas, use scaleDefault if ( MapWindow::zoom.RealScale()>scaleDefaultThreshold) { return; } // since we just checked category 10, if we are over scale we set nolabels if ( MapWindow::zoom.RealScale()>scaleThreshold) nolabels=true; } else if (MapWindow::zoom.RealScale() > scaleThreshold) return; // TODO code: only draw inside screen! // this will save time with rendering pixmaps especially // checkVisible does only check lat lon , not screen pixels.. // We need to check also screen. const auto hpOld = Surface.SelectObject(hPen); LKSurface::OldBrush hbOld {}; if (hbBrush) { hbOld = Surface.SelectObject(hbBrush); } const auto hfOld = Surface.SelectObject(MapTopologyFont); // get drawing info int iskip = 1; // attempt to bugfix 100615 polyline glitch with zoom over 33Km // do not skip points, if drawing coast lines which have a scaleThreshold of 100km! // != 5 and != 10 if (scaleCategory>10) { if (MapWindow::zoom.RealScale()>0.25*scaleThreshold) { iskip = 2; } if (MapWindow::zoom.RealScale()>0.5*scaleThreshold) { iskip = 3; } if (MapWindow::zoom.RealScale()>0.75*scaleThreshold) { iskip = 4; } } // use the already existing screenbounds_latlon, calculated by CalculateScreenPositions in MapWindow2 rectObj screenRect = MapWindow::screenbounds_latlon; static POINT pt[MAXCLIPPOLYGON]; for (int ixshp = 0; ixshp < shpfile.numshapes; ixshp++) { XShape *cshape = shpCache[ixshp]; if (!cshape || cshape->hide) continue; shapeObj *shape = &(cshape->shape); switch(shape->type) { case(MS_SHAPE_POINT):{ #if 101016 // -------------------------- NOT PRINTING ICONS --------------------------------------------- bool dobitmap=false; if (scaleCategory<90 || (MapWindow::zoom.RealScale()<2)) dobitmap=true; // first a latlon overlap check, only approximated because of fastcosine in latlon2screen if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; tt++) { for (int jj=0; jj< shape->line[tt].numpoints; jj++) { POINT sc; MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc); if (dobitmap) { // bugfix 101212 missing case for scaleCategory 0 (markers) if (scaleCategory==0||cshape->renderSpecial(Surface, sc.x, sc.y, rc)) MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); } else { cshape->renderSpecial(Surface, sc.x, sc.y, rc); } } } } #else // -------------------------- PRINTING ICONS --------------------------------------------- // no bitmaps for small town over a certain zoom level and no bitmap if no label at all levels bool nobitmap=false, noiconwithnolabel=false; if (scaleCategory==90 || scaleCategory==100) { noiconwithnolabel=true; if (MapWindow::MapScale>4) nobitmap=true; } if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; tt++) { for (int jj=0; jj< shape->line[tt].numpoints; jj++) { POINT sc; MapWindow::LatLon2Screen(shape->line[tt].point[jj].x, shape->line[tt].point[jj].y, sc); if (!nobitmap) #if 101016 // only paint icon if label is printed too if (noiconwithnolabel) { if (cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted)) MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); } else { MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); cshape->renderSpecial(Surface, sc.x, sc.y,labelprinted); } #else MapWindow::DrawBitmapIn(Surface, sc, hBitmap,true); cshape->renderSpecial(Surface, sc.x, sc.y); #endif } } } #endif // Use optimized point icons 1.23e break; case(MS_SHAPE_LINE): if (checkVisible(*shape, screenRect)) for (int tt = 0; tt < shape->numlines; ++tt) { int minx = rc.right; int miny = rc.bottom; int msize = min(shape->line[tt].numpoints, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize, 1); for (int jj=0; jj< msize; ++jj) { if (pt[jj].x<=minx) { minx = pt[jj].x; miny = pt[jj].y; } } Surface.Polyline(pt, msize, rc); cshape->renderSpecial(Surface,minx,miny,rc); } break; case(MS_SHAPE_POLYGON): // if it's a water area (nolabels), print shape up to defaultShape, but print // labels only up to custom label levels if ( nolabels ) { if (checkVisible(*shape, screenRect)) { for (int tt = 0; tt < shape->numlines; ++tt) { int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip); Surface.Polygon(pt, msize, rc); } } } else if (checkVisible(*shape, screenRect)) { for (int tt = 0; tt < shape->numlines; ++tt) { int minx = rc.right; int miny = rc.bottom; int msize = min(shape->line[tt].numpoints/iskip, MAXCLIPPOLYGON); MapWindow::LatLon2Screen(shape->line[tt].point, pt, msize*iskip, iskip); for (int jj=0; jj< msize; ++jj) { if (pt[jj].x<=minx) { minx = pt[jj].x; miny = pt[jj].y; } } Surface.Polygon(pt, msize, rc); cshape->renderSpecial(Surface,minx,miny,rc); } } break; default: break; } }
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(); } } } }
// This is painting traffic icons on the screen. void MapWindow::LKDrawFLARMTraffic(LKSurface& Surface, const RECT& rc, const ScreenProjection& _Proj, const POINT& Orig_Aircraft) { if (!EnableFLARMMap) return; if (!DrawInfo.FLARM_Available) return; // init scaled coords for traffic icon static int iCircleSize = 7; static int iRectangleSize = 4; static short tscaler=0; if (DoInit[MDI_DRAWFLARMTRAFFIC]) { switch (ScreenSize) { case ss480x640: case ss480x800: case ss800x480: case ss640x480: iCircleSize = 9; iRectangleSize = 5; tscaler=NIBLSCALE(7)-2; break; case ss240x320: case ss272x480: case ss320x240: case ss480x272: case ss480x234: case ss400x240: iCircleSize = 7; iRectangleSize = 4; tscaler=NIBLSCALE(13)-2; break; default: iCircleSize = 7; iRectangleSize = 4; tscaler=NIBLSCALE(7); break; } DoInit[MDI_DRAWFLARMTRAFFIC]=false; } POINT Arrow[5]; TCHAR lbuffer[50]; const auto hpold = Surface.SelectObject(LKPen_Black_N1); int i; int painted=0; // double dX, dY; TextInBoxMode_t displaymode = {0}; displaymode.NoSetFont = 1; #if 0 double screenrange = GetApproxScreenRange(); double scalefact = screenrange/6000.0; // FIX 100820 #endif const auto oldfont = Surface.SelectObject(LK8MapFont); for (i=0,painted=0; i<FLARM_MAX_TRAFFIC; i++) { // limit to 10 icons map traffic if (painted>=10) { i=FLARM_MAX_TRAFFIC; continue; } if ( (DrawInfo.FLARM_Traffic[i].ID !=0) && (DrawInfo.FLARM_Traffic[i].Status != LKT_ZOMBIE) ) { painted++; double target_lon; double target_lat; target_lon = DrawInfo.FLARM_Traffic[i].Longitude; target_lat = DrawInfo.FLARM_Traffic[i].Latitude; #if (0) // No scaling, wrong if ((EnableFLARMMap==2)&&(scalefact>1.0)) { double distance; double bearing; DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, target_lat, target_lon, &distance, &bearing); FindLatitudeLongitude(DrawInfo.Latitude, DrawInfo.Longitude, bearing, distance*scalefact, &target_lat, &target_lon); } #endif POINT sc, sc_name, sc_av; sc = _Proj.LonLat2Screen(target_lon, target_lat); sc_name = sc; sc_name.y -= NIBLSCALE(16); sc_av = sc_name; _tcscpy(lbuffer,_T("")); if (DrawInfo.FLARM_Traffic[i].Cn && DrawInfo.FLARM_Traffic[i].Cn[0]!=_T('?')) { // 100322 _tcscat(lbuffer,DrawInfo.FLARM_Traffic[i].Cn); } if (DrawInfo.FLARM_Traffic[i].Average30s>=0.1) { size_t len = _tcslen(lbuffer); if (len > 0) _stprintf(lbuffer + len,_T(":%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s); else _stprintf(lbuffer,_T("%.1f"),LIFTMODIFY*DrawInfo.FLARM_Traffic[i].Average30s); } displaymode.Border=1; if (_tcslen(lbuffer)>0) TextInBox(Surface, &rc, lbuffer, sc.x+tscaler, sc.y+tscaler, &displaymode, false); // red circle if ((DrawInfo.FLARM_Traffic[i].AlarmLevel>0) && (DrawInfo.FLARM_Traffic[i].AlarmLevel<4)) { DrawBitmapIn(Surface, sc, hFLARMTraffic,true); } #if 1 // 1 Arrow[0].x = -4; Arrow[0].y = 5; Arrow[1].x = 0; Arrow[1].y = -6; Arrow[2].x = 4; Arrow[2].y = 5; Arrow[3].x = 0; Arrow[3].y = 2; Arrow[4].x = -4; Arrow[4].y = 5; for (int q=0; q < 5; q++) { Arrow[q].x = (LONG) ((double)Arrow[q].x * 1.7); Arrow[q].y = (LONG) ((double)Arrow[q].y * 1.7); } #else Arrow[0].x = scaler[0]; Arrow[0].y = scaler[1]; Arrow[1].x = 0; Arrow[1].y = scaler[2]; Arrow[2].x = scaler[3]; Arrow[2].y = scaler[1]; Arrow[3].x = 0; Arrow[3].y = scaler[4]; Arrow[4].x = scaler[0]; Arrow[4].y = scaler[1]; #endif /* switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: Surface.SelectObject(yellowBrush); break; case LKT_ZOMBIE: Surface.SelectObject(redBrush); break; default: Surface.SelectObject(greenBrush); break; } */ /************************************************************************* * calculate climb color *************************************************************************/ int iVarioIdx = (int)(2*DrawInfo.FLARM_Traffic[i].Average30s -0.5)+NO_VARIO_COLORS/2; if(iVarioIdx < 0) iVarioIdx =0; if(iVarioIdx >= NO_VARIO_COLORS) iVarioIdx =NO_VARIO_COLORS-1; Surface.SelectObject(*variobrush[iVarioIdx]); switch (DrawInfo.FLARM_Traffic[i].Status) { // 100321 case LKT_GHOST: Surface.Rectangle(sc.x-iRectangleSize, sc.y-iRectangleSize,sc.x+iRectangleSize, sc.y+iRectangleSize); break; case LKT_ZOMBIE: Surface.DrawCircle(sc.x, sc.x, iCircleSize, rc, true ); break; default: PolygonRotateShift(Arrow, 5, sc.x, sc.y, DrawInfo.FLARM_Traffic[i].TrackBearing - DisplayAngle); Surface.Polygon(Arrow,5); break; } } } Surface.SelectObject(oldfont); Surface.SelectObject(hpold); }