void MapWindow::SuspendDrawingThread(void) { LockTerrainDataGraphics(); THREADRUNNING = FALSE; UnlockTerrainDataGraphics(); // SuspendThread(hDrawThread); }
void MapWindow::ResumeDrawingThread(void) { LockTerrainDataGraphics(); THREADRUNNING = TRUE; UnlockTerrainDataGraphics(); // ResumeThread(hDrawThread); }
// inititalise shapes for markers, not the text file surviving restarts void TopologyInitialiseMarks() { StartupStore(TEXT(". Initialise marks%s"),NEWLINE); LockTerrainDataGraphics(); // TODO code: - This convert to non-unicode will not support all languages // (some may use more complicated PATH names, containing Unicode) // char buffer[MAX_PATH]; // ConvertTToC(buffer, LocalPath(TEXT("xcsoar-marks"))); // DISABLED LocalPath // JMW localpath does NOT work for the shapefile renderer! if (topo_marks) { topo_marks->DeleteFiles(); delete topo_marks; } TCHAR buf[MAX_PATH]; LocalPath(buf, _T(LKD_CONF)); _tcscat(buf, _T(DIRSEP)); _tcscat(buf, _T(LKF_SMARKS)); topo_marks = new TopologyWriter(buf, LKColor(0xD0,0xD0,0xD0)); if (topo_marks) { topo_marks->scaleThreshold = 30.0; //topo_marks->scaleDefaultThreshold = 30.0; // 101212 topo_marks->scaleCategory = 0; // 101212 marked locations topo_marks->loadBitmap(IDB_MARK); } UnlockTerrainDataGraphics(); }
void TopologyCloseMarks() { StartupStore(TEXT(". CloseMarks%s"),NEWLINE); LockTerrainDataGraphics(); if (topo_marks) { topo_marks->DeleteFiles(); delete topo_marks; topo_marks = NULL; } UnlockTerrainDataGraphics(); }
void MapWindow::UpdateCaches(bool force) { // map was dirtied while we were drawing, so skip slow process // (unless we haven't done it for 2000 ms) if (MapWindow::ForceVisibilityScan) { force = true; MapWindow::ForceVisibilityScan = false; } // have some time, do shape file cache update if necessary LockTerrainDataGraphics(); SetTopologyBounds(DrawRect, force); UnlockTerrainDataGraphics(); }
void DrawMarks (const HDC hdc, const RECT rc) { LockTerrainDataGraphics(); if (topo_marks) { if (reset_marks) { topo_marks->Reset(); reset_marks = false; } topo_marks->Paint(hdc, rc); } UnlockTerrainDataGraphics(); }
void MapWindow::UpdateCaches(bool force) { // map was dirtied while we were drawing, so skip slow process // (unless we haven't done it for 2000 ms) #if RASTERCACHE DWORD fpsTimeThis; static DWORD fpsTimeMapCenter = 0; #endif if (MapWindow::ForceVisibilityScan) { force = true; MapWindow::ForceVisibilityScan = false; } // have some time, do shape file cache update if necessary LockTerrainDataGraphics(); SetTopologyBounds(MapRect, force); UnlockTerrainDataGraphics(); #if RASTERCACHE // JP2 no more supported, however if rastercache will ever be enabled.. // Must do this even if terrain is not displayed, because // raster terrain is used by terrain footprint etc. fpsTimeThis = ::GetTickCount(); // 100115 if (force || ( (fpsTimeThis - fpsTimeMapCenter) > 5000)) { fpsTimeMapCenter=fpsTimeThis; RasterTerrain::ServiceTerrainCenter(DrawInfo.Latitude, DrawInfo.Longitude); } fpsTimeThis = ::GetTickCount(); static DWORD fpsTimeLast_terrain=0; if (EnableTerrain) { if (RenderTimeAvailable() || ((fpsTimeThis-fpsTimeLast_terrain)>5000) || force) { fpsTimeLast_terrain = fpsTimeThis; RasterTerrain::ServiceCache(); } } #endif // RASTERCACHE }
void MapWindow::CloseDrawingThread(void) { #if TESTBENCH StartupStore(_T("... CloseDrawingThread started\n")); #endif CLOSETHREAD = TRUE; SetEvent(drawTriggerEvent); // wake self up LockTerrainDataGraphics(); SuspendDrawingThread(); UnlockTerrainDataGraphics(); #if TESTBENCH StartupStore(_T("... CloseDrawingThread waitforsingleobject\n")); #endif WaitForSingleObject(hDrawThread, INFINITE); #if TESTBENCH StartupStore(_T("... CloseDrawingThread wait THREADEXIT\n")); #endif while(!THREADEXIT) { Sleep(100); }; #if TESTBENCH StartupStore(_T("... CloseDrawingThread finished\n")); #endif }
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::RenderMapWindowBg(HDC hdc, const RECT rc, const POINT &Orig, const POINT &Orig_Aircraft) { HFONT hfOld; // Calculations are taking time and slow down painting of map, beware #define MULTICALC_MINROBIN 5 // minimum split #define MULTICALC_MAXROBIN 20 // max split static short multicalc_slot=0;// -1 (which becomes immediately 0) will force full loading on startup, but this is not good // because currently we are not waiting for ProgramStarted=3 // and the first scan is made while still initializing other things // TODO assign numslots with a function, based also on available CPU time short numslots=1; #if NEWSMARTZOOM static double quickdrawscale=0.0; static double delta_drawscale=1.0; #endif // If we have a BigZoom request, we serve it immediately without calculating anything // TODO: stretch the old map bitmap to the new zoom, while fastzooming if (QUICKDRAW) { goto fastzoom; } if (NumberOfWayPoints>200) { numslots=NumberOfWayPoints/400; // keep numslots optimal if (numslots<MULTICALC_MINROBIN) numslots=MULTICALC_MINROBIN; // seconds for full scan, as this is executed at 1Hz if (numslots>MULTICALC_MAXROBIN) numslots=MULTICALC_MAXROBIN; // When waypointnumber has changed, we wont be using an exceeded multicalc_slot, which would crash the sw // In this case, we shall probably continue for the first round to calculate without going from the beginning // but this is not a problem, we are round-robin all the time here. if (++multicalc_slot>numslots) multicalc_slot=1; } else { multicalc_slot=0; // forcing full scan } // Here we calculate arrival altitude, GD etc for map waypoints. Splitting with multicalc will result in delayed // updating of visible landables, for example. The nearest pages do this separately, with their own sorting. // Basically we assume -like for nearest- that values will not change that much in the multicalc split time. // Target and tasks are recalculated in real time in any case. Nearest too. LKCalculateWaypointReachable(multicalc_slot, numslots); CalculateScreenPositionsAirspace(); CalculateScreenPositionsThermalSources(); CalculateScreenPositionsGroundline(); if (PGZoomTrigger) { if(!mode.Is(Mode::MODE_PANORAMA)) { mode.Special(Mode::MODE_SPECIAL_PANORAMA, true); LastZoomTrigger=GPS_INFO.Time; Message::Lock(); Message::AddMessage(1000, 3, gettext(TEXT("_@M872_"))); // LANDSCAPE ZOOM FOR 20s Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEUP.WAV")); #endif } else { // previously called, see if time has passed if ( GPS_INFO.Time > (LastZoomTrigger + 20.0)) { // time has passed, lets go back LastZoomTrigger=0; // just for safety mode.Special(Mode::MODE_SPECIAL_PANORAMA, false); PGZoomTrigger=false; Message::Lock(); Message::AddMessage(1500, 3, gettext(TEXT("_@M873_"))); // BACK TO NORMAL ZOOM Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEDOWN.WAV")); #endif } } } // let the calculations run, but dont draw anything but the look8000 when in MapSpaceMode != MSM_MAP if (DONTDRAWTHEMAP) { QuickRedraw: // 100318 speedup redraw DrawLook8000(hdc,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif // no need to do SelectObject as at the bottom of function return; } // When no terrain is painted, set a background0 // Remember that in this case we have plenty of cpu time to spend for best result if (!EnableTerrain || !DerivedDrawInfo.TerrainValid || !RasterTerrain::isTerrainLoaded() ) { // display border and fill background.. SelectObject(hdc, hInvBackgroundBrush[BgMapColor]); SelectObject(hdc, GetStockObject(WHITE_PEN)); Rectangle(hdc,rc.left,rc.top,rc.right,rc.bottom); // We force LK painting black values on screen depending on the background color in use // TODO make it an array once settled // blackscreen would force everything to be painted white, instead LKTextBlack=BgMapColorTextBlack[BgMapColor]; if (BgMapColor>6 ) BlackScreen=true; else BlackScreen=false; } else { LKTextBlack=false; BlackScreen=false; } fastzoom: #if NEWSMARTZOOM // Copy the old background map with no overlays if (ONSMARTZOOM) { if (quickdrawscale>0) { delta_drawscale=zoom.DrawScale() / quickdrawscale; } // StartupStore(_T("... QuickDrawScale=%.2f new zoom=%.2f delta=%.2f\n"),quickdrawscale,zoom.DrawScale(),delta_drawscale); int dx=MapRect.right-MapRect.left; int dy=MapRect.bottom-MapRect.top; // notice: zoom in is always ok.. but zoom out starting from high zoom levels will make the picture // very small and unusable. We can consider to zoom out in fast zoom normally, in such cases? // // Notice 2: the delta is not yet working correctly // if (delta_drawscale>1.0) { // zoom in StretchBlt(hdcDrawWindow, 0,0, dx,dy, hdcQuickDrawWindow, (int)((dx/2) - (dx / delta_drawscale)/2), (int)((dy/2) - (dy / delta_drawscale)/2), (int)(dx / delta_drawscale), (int)(dy / delta_drawscale), SRCCOPY); } else { // zoom out StretchBlt(hdcDrawWindow, (int)((dx/2) - (dx * delta_drawscale)/2), (int)((dy/2) - (dy * delta_drawscale)/2), (int)(dx * delta_drawscale), (int)(dy * delta_drawscale), hdcQuickDrawWindow, 0,0, dx,dy, SRCCOPY); } } #endif SelectObject(hdc, GetStockObject(BLACK_BRUSH)); SelectObject(hdc, GetStockObject(BLACK_PEN)); hfOld = (HFONT)SelectObject(hdc, MapWindowFont); // ground first... if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } #if NEWSMARTZOOM if ( OFFSMARTZOOM ) { #endif if ((EnableTerrain && (DerivedDrawInfo.TerrainValid) && RasterTerrain::isTerrainLoaded()) ) { // sunelevation is never used, it is still a todo in Terrain double sunelevation = 40.0; double sunazimuth=GetAzimuth(); LockTerrainDataGraphics(); if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } DrawTerrain(hdc, rc, sunazimuth, sunelevation); // LOCKED 091105 if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if (!QUICKDRAW) { // shaded terrain unreachable, aka glide amoeba #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) { #else if ((FinalGlideTerrain==2) && DerivedDrawInfo.TerrainValid) { #endif DrawTerrainAbove(hdc, rc); } } UnlockTerrainDataGraphics(); } #if NEWSMARTZOOM } #endif if (QUICKDRAW) { if ( !mode.AnyPan()) DrawLook8000(hdc,rc); SelectObject(hdcDrawWindow, hfOld); return; } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if (EnableTopology) { DrawTopology(hdc, rc); // LOCKED 091105 } #if 0 StartupStore(_T("... Experimental1=%.0f\n"),Experimental1); StartupStore(_T("... Experimental2=%.0f\n"),Experimental2); Experimental1=0.0; Experimental2=0.0; #endif // Topology labels are printed first, using OLD wps positions from previous run! // Reset for topology labels decluttering engine occurs also in another place here! nLabelBlocks = 0; #if TOPOFASTLABEL for (short nvi=0; nvi<SCREENVSLOTS; nvi++) nVLabelBlocks[nvi]=0; #endif if (ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { // 100503 DrawTaskAAT(hdc, rc); } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if (OnAirSpace > 0) // Default is true, always true at startup no regsave { if ( (GetAirSpaceFillType() == asp_fill_ablend_full) || (GetAirSpaceFillType() == asp_fill_ablend_borders) ) DrawTptAirSpace(hdc, rc); else DrawAirSpace(hdc, rc); } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if(TrailActive) { // NEED REWRITING LKDrawTrail(hdc, Orig_Aircraft, rc); } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } DrawThermalEstimate(hdc, rc); if (OvertargetMode==OVT_THER) DrawThermalEstimateMultitarget(hdc, rc); // draw red cross on glide through terrain marker if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) { DrawGlideThroughTerrain(hdc, rc); } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if ((OnAirSpace > 0) && AirspaceWarningMapLabels) { DrawAirspaceLabels(hdc, rc, Orig_Aircraft); if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } } DrawWaypointsNew(hdc,rc); if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } if (ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { // 100503 DrawTask(hdc, rc, Orig_Aircraft); } DrawTeammate(hdc, rc); if (extGPSCONNECT) { DrawBestCruiseTrack(hdc, Orig_Aircraft); DrawBearing(hdc, rc); } // draw wind vector at aircraft if (!mode.AnyPan()) { DrawWindAtAircraft2(hdc, Orig_Aircraft, rc); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { DrawWindAtAircraft2(hdc, Orig, rc); } #if NEWSMARTZOOM // Save the current rendered map before painting overlays if ( OFFSMARTZOOM ) { quickdrawscale=zoom.DrawScale(); BitBlt(hdcQuickDrawWindow, 0, 0, MapRect.right-MapRect.left, MapRect.bottom-MapRect.top, hdcDrawWindow, 0, 0, SRCCOPY); } #endif // VisualGlide drawn BEFORE lk8000 overlays if (!mode.AnyPan() && VisualGlide > 0) { DrawGlideCircle(hdc, Orig, rc); } if (DONTDRAWTHEMAP) { // 100319 SelectObject(hdcDrawWindow, hfOld); goto QuickRedraw; } // Draw traffic and other specifix LK gauges LKDrawFLARMTraffic(hdc, rc, Orig_Aircraft); if (!mode.AnyPan()) { // REMINDER TODO let it be configurable for not circling also, as before if ((mode.Is(Mode::MODE_CIRCLING)) ) if (ThermalBar) DrawThermalBand(hdcDrawWindow, rc); // 091122 DrawLook8000(hdc,rc); } if (LKVarioBar && !mode.AnyPan()) // 091214 do not draw Vario when in Pan mode LKDrawVario(hdc,rc); // 091111 // Draw glider or paraglider if (extGPSCONNECT) { DrawAircraft(hdc, Orig_Aircraft); } if (!mode.AnyPan()) { if (TrackBar) DrawHeading(hdc, Orig, rc); } #if USETOPOMARKS // marks on top... DrawMarks(hdc, rc); #endif if (ISGAAIRCRAFT) DrawHSI(hdc,Orig,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif SelectObject(hdcDrawWindow, hfOld); }
// // Reinit screen upon resolution/orientation change detected // // Test is possible from VirtualKeys.cpp, activating the customkey at line 229 // In this case, enable a testbench development option. // void ReinitScreen(void) { static int oldSCREENWIDTH=0; static int oldSCREENHEIGHT=0; RECT WindowSize, rc; // This is needed to hide any menu currently on, as first thing. InputEvents::setMode(TEXT("default")); #if TESTBENCH StartupStore(_T("... ChangeScreen suspending Draw Thread\n")); #endif MapWindow::SuspendDrawingThread(); // MapWndProc will get a WM_SIZE // // Detect the current screen geometry // #if (WINDOWSPC>0) // For PC we assume that the desired resolution is in SCREENxx WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = SCREENWIDTH; WindowSize.bottom = SCREENHEIGHT; #else WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = GetSystemMetrics(SM_CXSCREEN); WindowSize.bottom = GetSystemMetrics(SM_CYSCREEN); #endif // // ----------- DEVELOPMENT TESTBENCH OPTIONS ------------- // #if 0 // Force a test resolution, for testing only! // Using always the same resolution will not work when asking for the same resolution again. // dont know why (yet)... WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = 480; WindowSize.bottom = 272; #endif #if 0 // Simulate changin one resolution to another static bool vhflip=true; if (vhflip) { WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = 480; WindowSize.bottom = 272; vhflip=false; } else { WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = 800; WindowSize.bottom = 480; vhflip=true;; } #endif #if 0 // Simulate Portrait<>Landscape flip/flop WindowSize.left = 0; WindowSize.top = 0; WindowSize.right = SCREENHEIGHT; WindowSize.bottom = SCREENWIDTH; #endif // // --------------------------------------------------------- // if (oldSCREENWIDTH!=WindowSize.right || oldSCREENHEIGHT!=WindowSize.bottom) { #if TESTBENCH StartupStore(_T(".... CHANGING RESOLUTION\n")); #endif #if (WINDOWSPC>0) SCREENWIDTH = WindowSize.right; SCREENHEIGHT= WindowSize.bottom; #endif oldSCREENWIDTH = WindowSize.right; oldSCREENHEIGHT= WindowSize.bottom; } else { // THIS DOES NOT STILL WORK! NO EFFECT. #if TESTBENCH StartupStore(_T(".... CHANGE RESOLUTION, SAME SIZE, WM_SIZE FORCED\n")); #endif #if (WINDOWSPC>0) SCREENWIDTH = WindowSize.right; SCREENHEIGHT= WindowSize.bottom; #endif SendMessage(hWndMapWindow, WM_SIZE, (WPARAM)SIZE_RESTORED, MAKELPARAM(0,0)); } #if (WINDOWSPC>0) WindowSize.right = SCREENWIDTH + 2*GetSystemMetrics( SM_CXFIXEDFRAME); WindowSize.left = (GetSystemMetrics(SM_CXSCREEN) - WindowSize.right) / 2; WindowSize.bottom = SCREENHEIGHT + 2*GetSystemMetrics( SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION); WindowSize.top = (GetSystemMetrics(SM_CYSCREEN) - WindowSize.bottom) / 2; // We must consider the command bar size on PC window MoveWindow(hWndMainWindow, WindowSize.left, WindowSize.top, WindowSize.right, WindowSize.bottom, TRUE); MoveWindow(hWndMapWindow, 0, 0, SCREENWIDTH, SCREENHEIGHT, FALSE); // also TRUE? #else // Still to be tested! MoveWindow(hWndMainWindow, WindowSize.left, WindowSize.top, WindowSize.right, WindowSize.bottom, TRUE); MoveWindow(hWndMapWindow, 0, 0, WindowSize.right, WindowSize.bottom, FALSE); #endif GetClientRect(hWndMainWindow, &rc); #if (WINDOWSPC>0) rc.left = 0; rc.right = SCREENWIDTH; rc.top = 0; rc.bottom = SCREENHEIGHT; #endif InitLKScreen(); LKSW_ReloadProfileBitmaps=true; LKObjects_Delete(); LKObjects_Create(); ButtonLabel::Destroy(); ButtonLabel::CreateButtonLabels(rc); extern void InitialiseFonts(RECT rc); InitialiseFonts(rc); InitLKFonts(); ButtonLabel::SetFont(MapWindowBoldFont); Message::Destroy(); Message::Initialize(rc); // creates window, sets fonts LockTerrainDataGraphics(); CloseTerrainRenderer(); UnlockTerrainDataGraphics(); Reset_Single_DoInits(MDI_DRAWLOOK8000); Reset_Single_DoInits(MDI_DRAWTRI); Reset_Single_DoInits(MDI_DRAWHSI); Reset_Single_DoInits(MDI_DRAWASPNEAREST); Reset_Single_DoInits(MDI_DRAWCOMMON); Reset_Single_DoInits(MDI_DRAWFLARMTRAFFIC); Reset_Single_DoInits(MDI_DRAWINFOPAGE); Reset_Single_DoInits(MDI_WRITEINFO); Reset_Single_DoInits(MDI_DRAWLOOK8000); Reset_Single_DoInits(MDI_DRAWMAPSPACE); Reset_Single_DoInits(MDI_DRAWNEAREST); Reset_Single_DoInits(MDI_DRAWTARGET); Reset_Single_DoInits(MDI_DRAWTHERMALHISTORY); Reset_Single_DoInits(MDI_DRAWTRAFFIC); Reset_Single_DoInits(MDI_DRAWVARIO); Reset_Single_DoInits(MDI_PROCESSVIRTUALKEY); Reset_Single_DoInits(MDI_ONPAINTLISTITEM); Reset_Single_DoInits(MDI_DRAWMAPSCALE); Reset_Single_DoInits(MDI_MAPWPLABELADD); Reset_Single_DoInits(MDI_CHECKLABELBLOCK); Reset_Single_DoInits(MDI_LKPROCESS); Reset_Single_DoInits(MDI_COMPASS); Reset_Single_DoInits(MDI_LOOKABLEND); Reset_Single_DoInits(MDI_MAPWPVECTORS); Reset_Single_DoInits(MDI_MAPASP); Reset_Single_DoInits(MDI_MAPRADAR); // doing nothing reallt Reset_Single_DoInits(MDI_FLARMRADAR); Reset_Single_DoInits(MDI_MAPWNDPROC); Reset_Single_DoInits(MDI_DRAWBOTTOMBAR); Reset_Single_DoInits(MDI_DRAWTASK); #if TESTBENCH StartupStore(_T("... ChangeScreen resuming Draw Thread\n")); #endif MapWindow::ResumeDrawingThread(); ShowWindow(hWndMainWindow, SW_SHOWNORMAL); BringWindowToTop(hWndMainWindow); return; }
void MapWindow::RenderMapWindowBg(LKSurface& Surface, const RECT& rc) { if ( (LKSurface::AlphaBlendSupported() && BarOpacity < 100) || mode.AnyPan() ) { RECT newRect = {0, 0, ScreenSizeX, ScreenSizeY}; MapWindow::ChangeDrawRect(newRect); } else { RECT newRect = {0, 0, ScreenSizeX, ScreenSizeY - BottomSize - (ScreenSizeY-MapRect.bottom)-1}; MapWindow::ChangeDrawRect(newRect); } if (QUICKDRAW) { goto _skip_calcs; } // Here we calculate arrival altitude, GD etc for map waypoints. Splitting with multicalc will result in delayed // updating of visible landables, for example. The nearest pages do this separately, with their own sorting. // Basically we assume -like for nearest- that values will not change that much in the multicalc split time. // Target and tasks are recalculated in real time in any case. Nearest too. LKCalculateWaypointReachable(false); _skip_calcs: if (PGZoomTrigger) { if (!mode.Is(Mode::MODE_PANORAMA)) { mode.Special(Mode::MODE_SPECIAL_PANORAMA, true); LastZoomTrigger = DrawInfo.Time; Message::AddMessage(1000, 3, gettext(TEXT("_@M872_"))); // LANDSCAPE ZOOM FOR 20s LKSound(TEXT("LK_TONEUP.WAV")); } else { // previously called, see if time has passed if (DrawInfo.Time > (LastZoomTrigger + 20.0)) { // time has passed, lets go back LastZoomTrigger = 0; // just for safety mode.Special(Mode::MODE_SPECIAL_PANORAMA, false); PGZoomTrigger = false; Message::AddMessage(1500, 3, gettext(TEXT("_@M873_"))); // BACK TO NORMAL ZOOM LKSound(TEXT("LK_TONEDOWN.WAV")); } } } // // "Checkpoint Charlie" // This is were we process stuff for anything else but main map. // We let the calculations run also for MapSpace modes. // But for multimaps, we can also draw some more stuff.. // We are also sent back here from next code, when we detect that // the MapSpace mode has changed from MAP to something else while we // were rendering. // QuickRedraw: // if (DONTDRAWTHEMAP) { const bool isMultimap = IsMultiMapShared(); // DrawMapSpace can change "MapSpaceMode", get this before. DrawMapSpace(Surface, rc); // Is this a "shared map" environment? if (isMultimap) { // Shared map, of course not MSN_MAP, since dontdrawthemap was checked // if (IsMultimapOverlaysGauges()) { RenderOverlayGauges(Surface, rc); } if (IsMultimapOverlaysText()) { DrawLook8000(Surface, rc); } } else { // Not in map painting environment // ex. nearest pages, but also MAPRADAR.. } // DrawBottomBar(Surface, rc); #ifdef DRAWDEBUG DrawDebug(hdc, rc); #endif // no need to do SelectObject as at the bottom of function return; } POINT Orig, Orig_Aircraft; CalculateOrigin(rc, &Orig); const ScreenProjection _Proj = CalculateScreenPositions(Orig, rc, &Orig_Aircraft); // When no terrain is painted, set a background0 // Remember that in this case we have plenty of cpu time to spend for best result if (!IsMultimapTerrain() || !DerivedDrawInfo.TerrainValid || !RasterTerrain::isTerrainLoaded()) { // We force LK painting black values on screen depending on the background color in use // TODO make it an array once settled // blackscreen would force everything to be painted white, instead LKTextBlack = BgMapColorTextBlack[BgMapColor]; if (BgMapColor > 6) BlackScreen = true; else BlackScreen = false; } else { LKTextBlack = false; BlackScreen = false; } // Logic of DONTDRAWTHEMAP is the following: // We are rendering the screen page here. If we are here, we passed Checkpoint Charlie. // So we were, at charlie, in MSM_MAP: preparing the main map stuff. // If we detect that MapSpace has CHANGED while we were doing our job here, // it means that the user has clicked meanwhile. He desires another page, so let's // reset our intentions and go back to beginning, or nearby.. // We have a new job to do, for another MapSpace, no more MAP. if (DONTDRAWTHEMAP) { goto QuickRedraw; } bool terrainpainted = false; if ((IsMultimapTerrain() && (DerivedDrawInfo.TerrainValid) && RasterTerrain::isTerrainLoaded()) ) { // sunelevation is never used, it is still a todo in Terrain double sunelevation = 40.0; double sunazimuth = GetAzimuth(); LockTerrainDataGraphics(); if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); goto QuickRedraw; } if(DrawTerrain(Surface, DrawRect, _Proj, sunazimuth, sunelevation)) { terrainpainted = true; } if (DONTDRAWTHEMAP) { UnlockTerrainDataGraphics(); goto QuickRedraw; } if (!QUICKDRAW) { // SHADED terrain unreachable, aka glide amoeba. This is not the outlined perimeter! #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) { #else if ((FinalGlideTerrain == 2) && DerivedDrawInfo.TerrainValid) { #endif DrawTerrainAbove(Surface, DrawRect); } } UnlockTerrainDataGraphics(); } // // REMINDER: WE ARE IN MAIN MAP HERE: MSM_MAP ONLY, OR PANNING MODE! // MAPSPACEMODE CAN STILL CHANGE, DUE TO USER INPUT. BUT WE GOT HERE IN // EITHER PAN OR MSM_MAP. // if (DONTDRAWTHEMAP) { goto QuickRedraw; } if(!terrainpainted) { // fill background.. Surface.FillRect(&rc, hInvBackgroundBrush[BgMapColor]); } if (IsMultimapTopology()) { DrawTopology(Surface, DrawRect, _Proj); } else { // If no topology wanted, but terrain painted, we paint only water stuff if (terrainpainted) DrawTopology(Surface, DrawRect, _Proj, true); } #if 0 StartupStore(_T("... Experimental1=%.0f\n"), Experimental1); StartupStore(_T("... Experimental2=%.0f\n"), Experimental2); Experimental1 = 0.0; Experimental2 = 0.0; #endif // Topology labels are printed first, using OLD wps positions from previous run! // Reset for topology labels decluttering engine occurs also in another place here! ResetLabelDeclutter(); if ((Flags_DrawTask || TargetDialogOpen) && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskAAT(Surface, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapAirspace()) { DrawAirSpace(Surface, rc, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // In QUICKDRAW dont draw trail, thermals, glide terrain if (QUICKDRAW) { goto _skip_stuff; } DrawThermalEstimate(Surface, DrawRect, _Proj); if (OvertargetMode == OVT_THER) DrawThermalEstimateMultitarget(Surface, DrawRect, _Proj); // draw red cross on glide through terrain marker if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) { DrawGlideThroughTerrain(Surface, DrawRect, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } _skip_stuff: if (IsMultimapAirspace() && AirspaceWarningMapLabels) { DrawAirspaceLabels(Surface, DrawRect, _Proj, Orig_Aircraft); if (DONTDRAWTHEMAP) { // 100319 goto QuickRedraw; } } if (IsMultimapWaypoints()) { DrawWaypointsNew(Surface, DrawRect); } if (TrailActive) { LKDrawLongTrail(Surface, Orig_Aircraft, DrawRect); // NEED REWRITING LKDrawTrail(Surface, DrawRect, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if ((Flags_DrawTask || TargetDialogOpen) && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTask(Surface, DrawRect, _Proj, Orig_Aircraft); } if (Flags_DrawFAI) { if (MapWindow::DerivedDrawInfo.Flying) { // FAI optimizer does not depend on tasks, being based on trace DrawFAIOptimizer(Surface, DrawRect, _Proj, Orig_Aircraft); } else { // not flying => show FAI sectors for the task if (ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskSectors(Surface, DrawRect, _Proj); } } } // In QUICKDRAW do not paint other useless stuff if (QUICKDRAW) { if (extGPSCONNECT) DrawBearing(Surface, DrawRect, _Proj); goto _skip_2; } // --------------------------------------------------- DrawTeammate(Surface, rc, _Proj); if (extGPSCONNECT) { DrawBestCruiseTrack(Surface, Orig_Aircraft); DrawBearing(Surface, DrawRect, _Proj); } // draw wind vector at aircraft if (NOTANYPAN) { DrawWindAtAircraft2(Surface, Orig_Aircraft, DrawRect); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { DrawWindAtAircraft2(Surface, Orig, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw traffic and other specifix LK gauges LKDrawFLARMTraffic(Surface, DrawRect, _Proj, Orig_Aircraft); // --------------------------------------------------- _skip_2: if (NOTANYPAN) { if (IsMultimapOverlaysGauges()) { RenderOverlayGauges(Surface, rc); } if (TrackBar) { DrawHeading(Surface, Orig, DrawRect); if (ISGAAIRCRAFT) { DrawFuturePos(Surface, Orig, DrawRect); } } if (ISGAAIRCRAFT) { DrawHSIarc(Surface, Orig, DrawRect); } if (IsMultimapOverlaysText()) { DrawLook8000(Surface, rc); } DrawBottomBar(Surface, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw glider or paraglider if (extGPSCONNECT) { DrawAircraft(Surface, Orig_Aircraft); } #if USETOPOMARKS // marks on top... DrawMarks(hdc, rc); #endif if (!INPAN) { DrawMapScale(Surface, rc, zoom.BigZoom()); // unused BigZoom DrawCompass(Surface, rc, DisplayAngle); } #ifdef DRAWDEBUG DrawDebug(hdc, rc); #endif }
// mode: 0 normal Change the topology scale of Category with newScale. // mode: 1 zoom more or less for the category with newScale (newScale is the zoom increment). // mode: 2 zoom more or less for all categories (tCategory is ignored, newScale is the zoom increment for all items) // mode: 3 reset default zoom for Category (newScale is ignored) // mode: 4 reset default zoom for all Categories (Category is ignored, newScale is ignored) void ChangeZoomTopology(int iCategory, double newScale, short cztmode) { if (LKTopo<1) return; LockTerrainDataGraphics(); if (cztmode==0) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology zindex=%d, categ=%d oldscale=%f newscale=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold = newScale; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==1) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology: zindex=%d, categ=%d oldscale=%f increment=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold += newScale; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==2) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology for all: zindex=%d, categ=%d oldscale=%f increment=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold += newScale; } } UnlockTerrainDataGraphics(); return; } if (cztmode==3) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology default zindex=%d, categ=%d oldscale=%f default=%f%s"), z,iCategory, TopoStore[z]->scaleThreshold, TopoStore[z]->scaleDefaultThreshold,NEWLINE); #endif TopoStore[z]->scaleThreshold = TopoStore[z]->scaleDefaultThreshold; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==4) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology all default zindex=%d, categ=%d oldscale=%f default=%f%s"), z,iCategory, TopoStore[z]->scaleThreshold, TopoStore[z]->scaleDefaultThreshold,NEWLINE); #endif TopoStore[z]->scaleThreshold = TopoStore[z]->scaleDefaultThreshold; } } UnlockTerrainDataGraphics(); return; } UnlockTerrainDataGraphics(); }
void WhereAmI::run(void) { #ifdef TESTBENCH StartupStore(_T("Oracle : start to find position") NEWLINE); #endif PeriodClock _time; _time.Update(); ResetNearestTopology(); LockTerrainDataGraphics(); const vectorObj center = { MapWindow::GetPanLongitude(), MapWindow::GetPanLatitude() }; rectObj bounds = { center.x, center.y, center.x, center.y }; for(int i = 0; i < 10; ++i) { double X, Y; FindLatitudeLongitude(center.y, center.x, i*360/10, 30*1000, &Y, &X ); bounds.minx = std::min(bounds.minx, X); bounds.maxx = std::max(bounds.maxx, X); bounds.miny = std::min(bounds.miny, Y); bounds.maxy = std::max(bounds.maxy, Y); } for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { // See also CheckScale for category checks! We should use a function in fact. if ( TopoStore[z]->scaleCategory == 10 || (TopoStore[z]->scaleCategory >= 70 && TopoStore[z]->scaleCategory <=100)) { TopoStore[z]->SearchNearest(bounds); } } } TCHAR ttmp[100]; double dist,wpdist,brg; NearestTopoItem *item=NULL; bool found=false, over=false, saynear=false, needmorewp=false, secondwpdone=false; #if TESTBENCH if (NearestBigCity.Valid) StartupStore(_T("... NEAREST BIG CITY <%s> at %.0f km brg=%.0f\n"), NearestBigCity.Name,NearestBigCity.Distance/1000,NearestBigCity.Bearing); if (NearestCity.Valid) StartupStore(_T("... NEAREST CITY <%s> at %.0f km brg=%.0f\n"), NearestCity.Name,NearestCity.Distance/1000,NearestCity.Bearing); if (NearestSmallCity.Valid) StartupStore(_T("... NEAREST TOWN <%s> at %.0f km brg=%.0f\n"), NearestSmallCity.Name,NearestSmallCity.Distance/1000,NearestSmallCity.Bearing); if (NearestWaterArea.Valid) StartupStore(_T("... NEAREST WATER AREA <%s> at %.0f km brg=%.0f\n"), NearestWaterArea.Name,NearestWaterArea.Distance/1000,NearestWaterArea.Bearing); #endif _stprintf(toracle,_T("%s\n\n"), MsgToken(1724)); // YOUR POSITION: if (NearestBigCity.Valid) { _tcscat(toracle, OracleFormatDistance(NearestBigCity.Name,MsgToken(1714), NearestBigCity.Distance, NearestBigCity.Bearing,0)); // the city _tcscat(toracle, _T("\n")); } if (NearestCity.Valid && NearestSmallCity.Valid) { if ( (NearestCity.Distance - NearestSmallCity.Distance) <=3000) item=&NearestCity; else item=&NearestSmallCity; } else { if (NearestCity.Valid) item=&NearestCity; else if (NearestSmallCity.Valid) item=&NearestSmallCity; } if (item) { dist=item->Distance; brg=item->Bearing; if (dist>1500) { // // 2km South of city // _stprintf(ttmp,_T("%.0f %s %s %s "), dist*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg), MsgToken(1715)); // of the city _tcscat(toracle,ttmp); } else { // // Over city // _stprintf(ttmp,_T("%s "),MsgToken(1716)); // Over the city _tcscat(toracle,ttmp); over=true; } _stprintf(ttmp,_T("<%s>"), item->Name); _tcscat(toracle,ttmp); found=true; } // Careful, some wide water areas have the center far away from us even if we are over them. // We can only check for 2-5km distances max. if (NearestWaterArea.Valid) { if (found) { if (NearestWaterArea.Distance<2000) { if (over) { // // Over city and lake // _stprintf(ttmp,_T(" %s %s"), MsgToken(1717),NearestWaterArea.Name); // and _tcscat(toracle,ttmp); saynear=true; } else { // // 2km South of city // over lake // _stprintf(ttmp,_T("\n%s %s"), MsgToken(1718),NearestWaterArea.Name); // over _tcscat(toracle,ttmp); saynear=true; } } else { if (NearestWaterArea.Distance<6000) { if (over) { // // Over city // near lake // _stprintf(ttmp,_T("\n%s %s"), MsgToken(1719),NearestWaterArea.Name); // near to _tcscat(toracle,ttmp); } else { // // 2km South of city // near lake // _stprintf(ttmp,_T("\n%s %s"), MsgToken(1718),NearestWaterArea.Name); // over _tcscat(toracle,ttmp); } } // else no mention to water area, even if it is the only item. Not accurate! } } else { if (NearestWaterArea.Distance>2000) { brg=NearestWaterArea.Bearing; // // 2km North of lake // _stprintf(ttmp,_T("%.0f %s %s "), NearestWaterArea.Distance*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg)); _tcscat(toracle,ttmp); _stprintf(ttmp,_T("%s <%s>"), MsgToken(1711),NearestWaterArea.Name); // of _tcscat(toracle,ttmp); } else { // // Over lake // _stprintf(ttmp,_T("%s <%s>"), MsgToken(1718),NearestWaterArea.Name); // over _tcscat(toracle,ttmp); over=true; } found=true; } } _tcscat(toracle,_T("\n")); // find nearest turnpoint & nearest Landable unsigned idx_nearest_airport = 0; unsigned idx_nearest_unknown = 0; { double dist_airport = std::numeric_limits<double>::max(); double dist_unknown = std::numeric_limits<double>::max(); for(unsigned i=NUMRESWP; i<WayPointList.size(); ++i) { if(WayPointList[i].Style == STYLE_THERMAL) continue; DistanceBearing(GPS_INFO.Latitude, GPS_INFO.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, &(WayPointCalc[i].Distance), &(WayPointCalc[i].Bearing)); if(WayPointCalc[i].Distance > 70000) continue; // To Far if(WayPointCalc[i].WpType == WPT_AIRPORT) { if(WayPointCalc[i].Distance < dist_airport) { dist_airport = WayPointCalc[i].Distance; idx_nearest_airport = i; } } if(WayPointCalc[i].Distance < dist_unknown) { dist_unknown = WayPointCalc[i].Distance; idx_nearest_unknown = i; } } } int j = idx_nearest_unknown; if (!ValidNotResWayPoint(j)) goto _end; found=true; _dowp: DistanceBearing( WayPointList[j].Latitude,WayPointList[j].Longitude, GPS_INFO.Latitude, GPS_INFO.Longitude, &wpdist,&brg); TCHAR wptype[100]; switch(WayPointList[j].Style) { case STYLE_AIRFIELDGRASS: case STYLE_GLIDERSITE: _stprintf(wptype,_T("%s "), MsgToken(1720)); // the airfield of break; case STYLE_OUTLANDING: _stprintf(wptype,_T("%s "), MsgToken(1721)); // the field of needmorewp=true; break; case STYLE_AIRFIELDSOLID: _stprintf(wptype,_T("%s "), MsgToken(1722)); // the airport of break; default: _tcscpy(wptype,_T("")); needmorewp=true; break; } if ( (_tcslen(wptype)==0) && WayPointCalc[j].IsLandable) { if (WayPointCalc[j].IsAirport) { _stprintf(wptype,_T("%s "), MsgToken(1720)); // the airfield of needmorewp=false; } else { _stprintf(wptype,_T("%s "), MsgToken(1721)); // the field of needmorewp=true; } } else { if (_tcslen(wptype)==0 ) { _tcscpy(wptype,_T("")); needmorewp=true; } } // nn km south if (wpdist>2000) { // // 2km South of city // and/over lake // 4 km SW of waypoint _stprintf(ttmp,_T("\n%.0f %s %s "), wpdist*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg)); _tcscat(toracle,ttmp); _stprintf(ttmp,_T("%s %s<%s>"), MsgToken(1711),wptype,WayPointList[j].Name); // of _tcscat(toracle,ttmp); } else { if (found) { if (over) { if (saynear) { // // 2km South of city // over lake // near waypoint // ---- // Over city and lake // near waypoint _stprintf(ttmp,_T("\n%s %s<%s>"), MsgToken(1719),wptype,WayPointList[j].Name); // near to _tcscat(toracle,ttmp); } else { // Over city // near lake and waypoint _stprintf(ttmp,_T(" %s %s<%s>"), MsgToken(1717),wptype,WayPointList[j].Name); // and _tcscat(toracle,ttmp); } } else { _stprintf(ttmp,_T("\n%s %s<%s>"), MsgToken(1719),wptype,WayPointList[j].Name); // near to _tcscat(toracle,ttmp); } } else { // // Near waypoint (because "over" could be wrong, we have altitudes in wp!) // _stprintf(ttmp,_T("%s %s<%s>"), MsgToken(1723),wptype,WayPointList[j].Name); // Near to _tcscat(toracle,ttmp); } } if (!needmorewp) goto _end; if (secondwpdone) goto _end; j=idx_nearest_airport; if (!ValidNotResWayPoint(j)) goto _end; secondwpdone=true; goto _dowp; _end: UnlockTerrainDataGraphics(); #ifdef ULLIS_PRIVATE_FEATURES _stprintf(ttmp,_T("\n\nin %i ft (MSL)"), (int)( GPS_INFO.Altitude*TOFEET)); // in height _tcscat(toracle,ttmp); #endif // VERY SORRY - YOUR POSITION IS UNKNOWN! if (!found) _stprintf(toracle,_T("\n\n%s\n\n%s"), MsgToken(1725),MsgToken(1726)); CharUpper(toracle); #ifdef TESTBENCH StartupStore(_T("Oracle : Result found in %d ms") NEWLINE, _time.Elapsed()); #endif }
// mode: 0 normal Change the topology scale of Category with newScale. // mode: 1 zoom more or less for the category with newScale (newScale is the zoom increment). // mode: 2 zoom more or less for all categories (tCategory is ignored, newScale is the zoom increment for all items) // mode: 3 reset default zoom for Category (newScale is ignored) // mode: 4 reset default zoom for all Categories (Category is ignored, newScale is ignored) void ChangeZoomTopology(int iCategory, double newScale, short cztmode) { if (LKTopo<1) return; LockTerrainDataGraphics(); if (cztmode==0) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology zindex=%d, categ=%d oldscale=%f newscale=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold = newScale; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==1) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology: zindex=%d, categ=%d oldscale=%f increment=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold += newScale; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==2) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology for all: zindex=%d, categ=%d oldscale=%f increment=%f%s"),z,iCategory, TopoStore[z]->scaleThreshold, newScale,NEWLINE); #endif TopoStore[z]->scaleThreshold += newScale; } } UnlockTerrainDataGraphics(); return; } if (cztmode==3) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { if ( TopoStore[z]->scaleCategory == iCategory ) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology default zindex=%d, categ=%d oldscale=%f default=%f%s"), z,iCategory, TopoStore[z]->scaleThreshold, TopoStore[z]->scaleDefaultThreshold,NEWLINE); #endif TopoStore[z]->scaleThreshold = TopoStore[z]->scaleDefaultThreshold; } } } UnlockTerrainDataGraphics(); return; } if (cztmode==4) { for (int z=0; z<MAXTOPOLOGY; z++) { if (TopoStore[z]) { #if DEBUG_LKTOPO StartupStore(_T("... ChangeZoomTopology all default zindex=%d, categ=%d oldscale=%f default=%f%s"), z,iCategory, TopoStore[z]->scaleThreshold, TopoStore[z]->scaleDefaultThreshold,NEWLINE); #endif // 130207 categories 5 and 10 are using DefaultThreshold for polygon paint, // and scaleThreshold for labels only. Upon reset, we should use the original // LKTopoZoom settings, because the Default is always fixed to 100! // Otherwise on reset we get 99.. even if we set LKTopoZoom to something else. // This is needed if we want to have a startup setting different from default // for these 05 and 10 categories only. // Sorry but water areas and labels are not easy to manage because we want to paint // blue all the way, but not also their labels. // Notice that since LKTopoZoom is saved to configuration, we cannot use it for reset! // This is why we have a special define DEFAULT_WATER_LABELS_THRESHOLD switch(TopoStore[z]->scaleCategory) { case 5: TopoStore[z]->scaleThreshold = DEFAULT_WATER_LABELS_THRESHOLD; break; case 10: TopoStore[z]->scaleThreshold = DEFAULT_WATER_LABELS_THRESHOLD; break; default: TopoStore[z]->scaleThreshold = TopoStore[z]->scaleDefaultThreshold; break; } } } UnlockTerrainDataGraphics(); return; } UnlockTerrainDataGraphics(); }
void MapWindow::RenderMapWindowBg(HDC hdc, const RECT rc, const POINT &Orig, const POINT &Orig_Aircraft) { // Calculations are taking time and slow down painting of map, beware #define MULTICALC_MINROBIN 5 // minimum split #define MULTICALC_MAXROBIN 20 // max split static short multicalc_slot=0;// -1 (which becomes immediately 0) will force full loading on startup, but this is not good // because currently we are not waiting for ProgramStarted=3 // and the first scan is made while still initializing other things // TODO assign numslots with a function, based also on available CPU time short numslots=1; #if NEWSMARTZOOM static double quickdrawscale=0.0; static double delta_drawscale=1.0; #endif #if 0 extern void TestChangeRect(); TestChangeRect(); #endif if ((MapWindow::AlphaBlendSupported() && BarOpacity<100) || mode.AnyPan()) { MapWindow::ChangeDrawRect(MapRect); } else { RECT newRect={0,0,ScreenSizeX,ScreenSizeY-BottomSize}; MapWindow::ChangeDrawRect(newRect); } if (QUICKDRAW) { goto _skip_calcs; } if (NumberOfWayPoints>200) { numslots=NumberOfWayPoints/400; // keep numslots optimal if (numslots<MULTICALC_MINROBIN) numslots=MULTICALC_MINROBIN; // seconds for full scan, as this is executed at 1Hz if (numslots>MULTICALC_MAXROBIN) numslots=MULTICALC_MAXROBIN; // When waypointnumber has changed, we wont be using an exceeded multicalc_slot, which would crash the sw // In this case, we shall probably continue for the first round to calculate without going from the beginning // but this is not a problem, we are round-robin all the time here. if (++multicalc_slot>numslots) multicalc_slot=1; } else { multicalc_slot=0; // forcing full scan } // Here we calculate arrival altitude, GD etc for map waypoints. Splitting with multicalc will result in delayed // updating of visible landables, for example. The nearest pages do this separately, with their own sorting. // Basically we assume -like for nearest- that values will not change that much in the multicalc split time. // Target and tasks are recalculated in real time in any case. Nearest too. LKCalculateWaypointReachable(multicalc_slot, numslots); _skip_calcs: CalculateScreenPositionsAirspace(rc); CalculateScreenPositionsThermalSources(); // Make the glide amoeba out of the latlon points, converting them to screen // (This function is updated for supporting multimaps ) CalculateScreenPositionsGroundline(); if (PGZoomTrigger) { if(!mode.Is(Mode::MODE_PANORAMA)) { mode.Special(Mode::MODE_SPECIAL_PANORAMA, true); LastZoomTrigger=DrawInfo.Time; Message::Lock(); Message::AddMessage(1000, 3, gettext(TEXT("_@M872_"))); // LANDSCAPE ZOOM FOR 20s Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEUP.WAV")); #endif } else { // previously called, see if time has passed if ( DrawInfo.Time > (LastZoomTrigger + 20.0)) { // time has passed, lets go back LastZoomTrigger=0; // just for safety mode.Special(Mode::MODE_SPECIAL_PANORAMA, false); PGZoomTrigger=false; Message::Lock(); Message::AddMessage(1500, 3, gettext(TEXT("_@M873_"))); // BACK TO NORMAL ZOOM Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEDOWN.WAV")); #endif } } } // // "Checkpoint Charlie" // This is were we process stuff for anything else but main map. // We let the calculations run also for MapSpace modes. // But for multimaps, we can also draw some more stuff.. // We are also sent back here from next code, when we detect that // the MapSpace mode has changed from MAP to something else while we // were rendering. // QuickRedraw: // if (DONTDRAWTHEMAP) { DrawMapSpace(hdc, rc); // Is this a "shared map" environment? if (IsMultiMapShared()) { // Shared map, of course not MSN_MAP, since dontdrawthemap was checked // if (IsMultimapOverlaysText()) { DrawLook8000(hdc,rc); } if (IsMultimapOverlaysGauges()) { if (LKVarioBar) LKDrawVario(hdc,rc); if ((mode.Is(Mode::MODE_CIRCLING)) ) if (ThermalBar) DrawThermalBand(hdcDrawWindow, rc); DrawFinalGlide(hdcDrawWindow,rc); } } else { // Not in map painting environment // ex. nearest pages, but also MAPRADAR.. } // DrawBottomBar(hdc,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif // no need to do SelectObject as at the bottom of function return; } // When no terrain is painted, set a background0 // Remember that in this case we have plenty of cpu time to spend for best result if (!IsMultimapTerrain() || !DerivedDrawInfo.TerrainValid || !RasterTerrain::isTerrainLoaded() ) { // display border and fill background.. SelectObject(hdc, hInvBackgroundBrush[BgMapColor]); SelectObject(hdc, GetStockObject(WHITE_PEN)); Rectangle(hdc,rc.left,rc.top,rc.right,rc.bottom); // We force LK painting black values on screen depending on the background color in use // TODO make it an array once settled // blackscreen would force everything to be painted white, instead LKTextBlack=BgMapColorTextBlack[BgMapColor]; if (BgMapColor>6 ) BlackScreen=true; else BlackScreen=false; } else { LKTextBlack=false; BlackScreen=false; } #if NEWSMARTZOOM // Copy the old background map with no overlays if (ONSMARTZOOM) { if (quickdrawscale>0) { delta_drawscale=zoom.DrawScale() / quickdrawscale; } // StartupStore(_T("... QuickDrawScale=%.2f new zoom=%.2f delta=%.2f\n"),quickdrawscale,zoom.DrawScale(),delta_drawscale); int dx=MapRect.right-MapRect.left; int dy=MapRect.bottom-MapRect.top; // notice: zoom in is always ok.. but zoom out starting from high zoom levels will make the picture // very small and unusable. We can consider to zoom out in fast zoom normally, in such cases? // // Notice 2: the delta is not yet working correctly // if (delta_drawscale>1.0) { // zoom in StretchBlt(hdcDrawWindow, 0,0, dx,dy, hdcQuickDrawWindow, (int)((dx/2) - (dx / delta_drawscale)/2), (int)((dy/2) - (dy / delta_drawscale)/2), (int)(dx / delta_drawscale), (int)(dy / delta_drawscale), SRCCOPY); } else { // zoom out StretchBlt(hdcDrawWindow, (int)((dx/2) - (dx * delta_drawscale)/2), (int)((dy/2) - (dy * delta_drawscale)/2), (int)(dx * delta_drawscale), (int)(dy * delta_drawscale), hdcQuickDrawWindow, 0,0, dx,dy, SRCCOPY); } } #endif // Logic of DONTDRAWTHEMAP is the following: // We are rendering the screen page here. If we are here, we passed Checkpoint Charlie. // So we were, at charlie, in MSM_MAP: preparing the main map stuff. // If we detect that MapSpace has CHANGED while we were doing our job here, // it means that the user has clicked meanwhile. He desires another page, so let's // reset our intentions and go back to beginning, or nearby.. // We have a new job to do, for another MapSpace, no more MAP. if (DONTDRAWTHEMAP) { goto QuickRedraw; } #if NEWSMARTZOOM if ( OFFSMARTZOOM ) { #endif bool terrainpainted=false; if ((IsMultimapTerrain() && (DerivedDrawInfo.TerrainValid) && RasterTerrain::isTerrainLoaded()) ) { // sunelevation is never used, it is still a todo in Terrain double sunelevation = 40.0; double sunazimuth=GetAzimuth(); LockTerrainDataGraphics(); if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); goto QuickRedraw; } DrawTerrain(hdc, DrawRect, sunazimuth, sunelevation); terrainpainted=true; if (DONTDRAWTHEMAP) { UnlockTerrainDataGraphics(); goto QuickRedraw; } if (!QUICKDRAW) { // SHADED terrain unreachable, aka glide amoeba. This is not the outlined perimeter! #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) { #else if ((FinalGlideTerrain==2) && DerivedDrawInfo.TerrainValid) { #endif DrawTerrainAbove(hdc, DrawRect); } } UnlockTerrainDataGraphics(); } #if NEWSMARTZOOM } #endif // // REMINDER: WE ARE IN MAIN MAP HERE: MSM_MAP ONLY, OR PANNING MODE! // MAPSPACEMODE CAN STILL CHANGE, DUE TO USER INPUT. BUT WE GOT HERE IN // EITHER PAN OR MSM_MAP. // if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapTopology()) { DrawTopology(hdc, DrawRect); } else { // If no topology wanted, but terrain painted, we paint only water stuff if (terrainpainted) DrawTopology(hdc, DrawRect,true); } #if 0 StartupStore(_T("... Experimental1=%.0f\n"),Experimental1); StartupStore(_T("... Experimental2=%.0f\n"),Experimental2); Experimental1=0.0; Experimental2=0.0; #endif // Topology labels are printed first, using OLD wps positions from previous run! // Reset for topology labels decluttering engine occurs also in another place here! ResetLabelDeclutter(); if (Flags_DrawTask && ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { DrawTaskAAT(hdc, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapAirspace()) { if ( (GetAirSpaceFillType() == asp_fill_ablend_full) || (GetAirSpaceFillType() == asp_fill_ablend_borders) ) DrawTptAirSpace(hdc, rc); else DrawAirSpace(hdc, rc); // full screen, to hide clipping effect on low border } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // In QUICKDRAW dont draw trail, thermals, glide terrain if (QUICKDRAW) goto _skip_stuff; if(TrailActive) { // NEED REWRITING LKDrawTrail(hdc, Orig_Aircraft, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } DrawThermalEstimate(hdc, DrawRect); if (OvertargetMode==OVT_THER) DrawThermalEstimateMultitarget(hdc, DrawRect); // draw red cross on glide through terrain marker if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) { DrawGlideThroughTerrain(hdc, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } _skip_stuff: if (IsMultimapAirspace() && AirspaceWarningMapLabels) { DrawAirspaceLabels(hdc, DrawRect, Orig_Aircraft); if (DONTDRAWTHEMAP) { // 100319 goto QuickRedraw; } } if (IsMultimapWaypoints()) { DrawWaypointsNew(hdc,DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (Flags_DrawTask && ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { DrawTask(hdc, DrawRect, Orig_Aircraft); } // FAI optimizer does not depend on tasks, being based on trace if (Flags_DrawFAI) DrawFAIOptimizer(hdc, DrawRect, Orig_Aircraft); // In QUICKDRAW do not paint other useless stuff if (QUICKDRAW) { if (extGPSCONNECT) DrawBearing(hdc, DrawRect); goto _skip_2; } // --------------------------------------------------- DrawTeammate(hdc, rc); if (extGPSCONNECT) { DrawBestCruiseTrack(hdc, Orig_Aircraft); DrawBearing(hdc, DrawRect); } // draw wind vector at aircraft if (NOTANYPAN) { DrawWindAtAircraft2(hdc, Orig_Aircraft, DrawRect); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { DrawWindAtAircraft2(hdc, Orig, rc); } #if NEWSMARTZOOM // Save the current rendered map before painting overlays if ( OFFSMARTZOOM ) { quickdrawscale=zoom.DrawScale(); BitBlt(hdcQuickDrawWindow, 0, 0, MapRect.right-MapRect.left, MapRect.bottom-MapRect.top, hdcDrawWindow, 0, 0, SRCCOPY); } #endif // VisualGlide drawn BEFORE lk8000 overlays if (NOTANYPAN && (VisualGlide > 0)) { DrawGlideCircle(hdc, Orig, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw traffic and other specifix LK gauges LKDrawFLARMTraffic(hdc, DrawRect, Orig_Aircraft); // --------------------------------------------------- _skip_2: if (NOTANYPAN) { // REMINDER TODO let it be configurable for not circling also, as before if ((mode.Is(Mode::MODE_CIRCLING)) ) if (ThermalBar) DrawThermalBand(hdcDrawWindow, rc); // 091122 if (IsMultimapOverlaysText()) DrawLook8000(hdc,rc); DrawBottomBar(hdc,rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapOverlaysGauges() && (LKVarioBar && NOTANYPAN)) LKDrawVario(hdc,rc); // Draw glider or paraglider if (extGPSCONNECT) { DrawAircraft(hdc, Orig_Aircraft); } if (NOTANYPAN && !QUICKDRAW) { if (TrackBar) DrawHeading(hdc, Orig, DrawRect); } #if USETOPOMARKS // marks on top... DrawMarks(hdc, rc); #endif if (ISGAAIRCRAFT && IsMultimapOverlaysGauges() && NOTANYPAN) DrawHSI(hdc,Orig,DrawRect); if (!INPAN) { DrawMapScale(hdcDrawWindow,rc, zoom.BigZoom()); // unused BigZoom DrawCompass(hdcDrawWindow, rc, DisplayAngle); } if (IsMultimapOverlaysGauges() && NOTANYPAN) DrawFinalGlide(hdcDrawWindow,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif }
void SettingsLeave() { if (!GlobalRunning) return; SwitchToMapWindow(); // Locking everything here prevents the calculation thread from running, // while shared data is potentially reloaded. LockFlightData(); LockTaskData(); MenuActive = false; // 101020 LKmaps contain only topology , so no need to force total reload! if(MAPFILECHANGED) { #if TESTBENCH StartupStore(_T(".... MAPFILECHANGED from configuration\n")); #endif if (LKTopo==0) { AIRSPACEFILECHANGED = TRUE; AIRFIELDFILECHANGED = TRUE; WAYPOINTFILECHANGED = TRUE; TERRAINFILECHANGED = TRUE; } TOPOLOGYFILECHANGED = TRUE; } if (TERRAINFILECHANGED) { #if TESTBENCH StartupStore(_T(".... TERRAINFILECHANGED from configuration\n")); #endif LockTerrainDataGraphics(); RasterTerrain::CloseTerrain(); RasterTerrain::OpenTerrain(); UnlockTerrainDataGraphics(); // NO! We dont reload waypoints on terrain change. // SetHome(WAYPOINTFILECHANGED==TRUE); MapWindow::ForceVisibilityScan = true; } if((WAYPOINTFILECHANGED) || (AIRFIELDFILECHANGED)) { #if TESTBENCH StartupStore(_T(".... WAYPOINT OR AIRFIELD CHANGED from configuration\n")); #endif SaveDefaultTask(); //@ 101020 BUGFIX ClearTask(); ReadWayPoints(); StartupStore(_T(". RELOADED %d WAYPOINTS + %u virtuals%s"),(unsigned)WayPointList.size()-NUMRESWP,NUMRESWP,NEWLINE); SetHome(true); // force home reload if (WAYPOINTFILECHANGED) { #if TESTBENCH StartupStore(_T(".... WAYPOINTFILECHANGED from configuration\n")); #endif SaveRecentList(); LoadRecentList(); RangeLandableNumber=0; RangeAirportNumber=0; RangeTurnpointNumber=0; CommonNumber=0; SortedNumber=0; // SortedTurnpointNumber=0; 101222 LastDoRangeWaypointListTime=0; LKForceDoCommon=true; LKForceDoNearest=true; LKForceDoRecent=true; // LKForceDoNearestTurnpoint=true; 101222 } InputEvents::eventTaskLoad(_T(LKF_DEFAULTASK)); //@ BUGFIX 101020 } if (TOPOLOGYFILECHANGED) { #if TESTBENCH StartupStore(_T(".... TOPOLOGYFILECHANGED from configuration\n")); #endif CloseTopology(); OpenTopology(); MapWindow::ForceVisibilityScan = true; } if(AIRSPACEFILECHANGED) { #if TESTBENCH StartupStore(_T(".... AIRSPACEFILECHANGED from configuration\n")); #endif CAirspaceManager::Instance().CloseAirspaces(); CAirspaceManager::Instance().ReadAirspaces(); CAirspaceManager::Instance().SortAirspaces(); MapWindow::ForceVisibilityScan = true; } if (POLARFILECHANGED) { #if TESTBENCH StartupStore(_T(".... POLARFILECHANGED from configuration\n")); #endif CalculateNewPolarCoef(); GlidePolar::SetBallast(); } if (AIRFIELDFILECHANGED || AIRSPACEFILECHANGED || WAYPOINTFILECHANGED || TERRAINFILECHANGED || TOPOLOGYFILECHANGED ) { CloseProgressDialog(); MainWindow.SetFocus(); } extern void ReinitScreen(void); if (FONTSCHANGED || AIRCRAFTTYPECHANGED) { ReinitScreen(); } UnlockTaskData(); UnlockFlightData(); if(!SIMMODE && COMPORTCHANGED) { #if TESTBENCH StartupStore(_T(".... COMPORTCHANGED from configuration. ForceComPortReset @%s\n"),WhatTimeIsIt()); #endif LKForceComPortReset=true; // RestartCommPorts(); 110605 } MapWindow::ResumeDrawingThread(); // allow map and calculations threads to continue on their merry way }
void MarkLocation(const double lon, const double lat, const double altitude) #endif { #if USETOPOMARKS LockTerrainDataGraphics(); if (topo_marks) { topo_marks->addPoint(lon, lat); topo_marks->triggerUpdateCache = true; } UnlockTerrainDataGraphics(); #endif char message[160]; FILE *stream; TCHAR tstring[50]; bool dopreambol=false; TCHAR fname[MAX_PATH]; LocalPath(fname,TEXT(LKD_WAYPOINTS)); _tcscat(fname,_T("\\")); _stprintf(tstring,_T("LK%04d%02d%02d.cup"), GPS_INFO.Year,GPS_INFO.Month,GPS_INFO.Day); _tcscat(fname,tstring); stream = _tfopen(fname,TEXT("r")); if (stream == NULL) dopreambol=true; else fclose(stream); stream = _tfopen(fname,TEXT("a+")); if (stream != NULL){ if (dopreambol) { // file was created empty, we need to add preambol header for CUP strcpy(message,"name,code,country,lat,lon,elev,style,rwdir,rwlen,freq,desc\r\n"); fwrite(message,strlen(message),1,stream); } char marktime[10], slat[20], slon[20], snear[50]; Units::TimeToTextSimple(tstring,TimeLocal((int)GPS_INFO.Time)); unicodetoascii(tstring,_tcslen(tstring),marktime); LatitudeToCUPString(lat,tstring); unicodetoascii(tstring,_tcslen(tstring),slat); LongitudeToCUPString(lon,tstring); unicodetoascii(tstring,_tcslen(tstring),slon); int j=FindNearestFarVisibleWayPoint(lon,lat,15000,WPT_UNKNOWN); if (j>0) { _tcscpy(tstring,WayPointList[j].Name); // Name is sized NAME_SIZE, 30, so ok with tstring[50] tstring[19]='\0'; // sized 20 chars unicodetoascii(tstring,_tcslen(tstring),snear); } else { strcpy(snear,"unknown"); } sprintf(message,"MK%s%02d,LK8000,,%s,%s,%d.0m,1,,,,Created on %02d-%02d-%04d at h%s near: %s\r\n", marktime,GPS_INFO.Second,slat,slon, iround((int)altitude), GPS_INFO.Day,GPS_INFO.Month,GPS_INFO.Year, marktime, snear ); fwrite(message,strlen(message),1,stream); fclose(stream); extern int GetVirtualWaypointMarkerSlot(void); j=GetVirtualWaypointMarkerSlot(); WayPointList[j].Latitude=lat; WayPointList[j].Longitude=lon; WayPointList[j].Altitude=altitude; WayPointList[j].Visible=TRUE; WayPointList[j].FarVisible=TRUE; wsprintf(WayPointList[j].Name,_T("MK%S%02d"),marktime,GPS_INFO.Second); #if BUGSTOP LKASSERT(WayPointList[j].Comment!=NULL); #endif if (WayPointList[j].Comment!=NULL) wsprintf(WayPointList[j].Comment,_T("Near: %hs"),snear); WayPointCalc[j].WpType=WPT_TURNPOINT; // Force updating DoRange otherwise it will pass up to 3 minutes // before this marker appears in the 2.3 tps page LastDoRangeWaypointListTime=0; } }
void MapWindow::LKDrawMultimap_Test(LKSurface& Surface, const RECT& rc) { if (DoInit[MDI_MAPTEST]) { // init statics here and then clear init to false DoInit[MDI_MAPTEST]=false; } // // X,Y coordinates of last clicked point on screen // These coordinates are related to any point clicked, even for a page flip, for bottom bar etc. // In some cases, you will read old coordinates because for example after clicking in the center of // bottom bar, the page changed out of multimap and entered nearest pages. // int X=startScreen.x; int Y=startScreen.y; // // Duration of key is inside long VKtime, in milliseconds. // // // Draw a boxed terrain/topology example // -------------------------------------- // RECT rct=rc; // desired area is 400x180, topleft is (20,30) rct.top=20; rct.bottom=rct.top+180; rct.left=30; rct.right=rct.left+400; MapWindow::ChangeDrawRect(rct); // set new area for terrain and topology PanLatitude = DrawInfo.Latitude; PanLongitude = DrawInfo.Longitude; // Current position is in center map POINT Orig = { (rct.right-rct.left)/2,(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); double sunelevation = 40.0; double sunazimuth=GetAzimuth(); if (IsMultimapTerrain() && DerivedDrawInfo.TerrainValid) { LockTerrainDataGraphics(); DrawTerrain(Surface, rct, _Proj, sunazimuth, sunelevation); UnlockTerrainDataGraphics(); } ResetLabelDeclutter(); // This is needed to reset at each run the declutter, for topology and waypoints! // SaturateLabelDeclutter(); // Use this to force no labels be printed, from now on. DrawTopology(Surface, rct, _Proj); DrawAirSpace(Surface, rct, _Proj); // ResetLabelDeclutter(); // If you saturated labels for topology, now you can reset the declutter to allow // printing only waypoints, DrawWaypointsNew(Surface,rct); const auto oldpen = Surface.SelectObject(LKPen_White_N1); const auto oldbrush = Surface.SelectObject(LKBrush_LightGrey); LKWriteBoxedText(Surface, rct, _T("MULTIMAP PAGE EXAMPLE"), 1, 1, WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); TCHAR ttext[100]; switch(LKevent) { // // USABLE EVENTS // case LKEVENT_NEWRUN: // CALLED ON ENTRY: when we select this page coming from another mapspace _tcscpy(ttext,_T("Event = NEW RUN")); break; case LKEVENT_UP: // click on upper part of screen, excluding center _tcscpy(ttext,_T("Event = UP")); break; case LKEVENT_DOWN: // click on lower part of screen, excluding center _tcscpy(ttext,_T("Event = DOWN")); break; case LKEVENT_LONGCLICK: _stprintf(ttext,_T("Event = LONG CLICK")); break; case LKEVENT_PAGEUP: _tcscpy(ttext,_T("Event = PAGE UP")); break; case LKEVENT_PAGEDOWN: _tcscpy(ttext,_T("Event = PAGE DOWN")); break; case LKEVENT_TOPLEFT: _tcscpy(ttext,_T("Event = TOP LEFT")); break; case LKEVENT_TOPRIGHT: _tcscpy(ttext,_T("Event = TOP RIGHT")); break; case LKEVENT_SHORTCLICK: _tcscpy(ttext,_T("Event = SHORT CLICK")); break; // // THESE EVENTS ARE NOT AVAILABLE IN MULTIMAPS! // case LKEVENT_ENTER: // click longer on center, like to confirm a selection _tcscpy(ttext,_T("Event = ENTER")); break; case LKEVENT_NEWPAGE: // swipe gesture up/down produces NEW PAGE in this case _tcscpy(ttext,_T("Event = NEW PAGE")); break; case LKEVENT_NONE: // Normally no event. _tcscpy(ttext,_T("Event = NONE")); break; // default: // THIS SHOULD NEVER HAPPEN, but always CHECK FOR IT! _tcscpy(ttext,_T("Event = unknown")); break; } LKWriteBoxedText(Surface, rct, ttext, 1, 50 , WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); // // Be sure to check that an EVENT was generated, otherwise you are checking even bottombar key presses. // if (LKevent!=LKEVENT_NONE) { _stprintf(ttext,_T("Last coords: X=%d Y=%d , duration=%ld ms"),X,Y,VKtime); LKWriteBoxedText(Surface, rct, ttext, 1, 100 , WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); } // After using the event, WE MUST CLEAR IT, otherwise it will survive for next run. // This can be good for something, though, like automatic redo of last action. // You can also clear this event at the end of this function, to know during execution which was // the key pressed, but remember to clear it. LKevent=LKEVENT_NONE; Surface.SelectObject(oldbrush); Surface.SelectObject(oldpen); }