Example #1
0
void MapWindow::SuspendDrawingThread(void)
{
  LockTerrainDataGraphics();
  THREADRUNNING = FALSE;
  UnlockTerrainDataGraphics();
  //  SuspendThread(hDrawThread);
}
Example #2
0
void MapWindow::ResumeDrawingThread(void)
{
  LockTerrainDataGraphics();
  THREADRUNNING = TRUE;
  UnlockTerrainDataGraphics();
  //  ResumeThread(hDrawThread);
}
Example #3
0
// 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();
}
Example #4
0
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();
}
Example #6
0
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();

}
Example #7
0
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
}
Example #8
0
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
}
Example #9
0
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;

}
Example #10
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);

}
Example #11
0
//
// 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;
}
Example #12
0
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

}
Example #13
0
// 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();
}
Example #14
0
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
}
Example #15
0
// 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();
}
Example #16
0
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

}
Example #17
0
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
}
Example #18
0
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; 
  }

}
Example #19
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);


}