Exemplo n.º 1
0
bool DevLX16xx::PutGPRMB(PDeviceDescriptor_t d)
{

//RMB - The recommended minimum navigation sentence is sent whenever a route or a goto is active.
//      On some systems it is sent all of the time with null data.
//      The Arrival alarm flag is similar to the arrival alarm inside the unit and can be decoded to
//      drive an external alarm.
//      Note: the use of leading zeros in this message to preserve the character spacing.
//      This is done, I believe, because some autopilots may depend on exact character spacing.
//
//     $GPRMB,A,0.66,L,003,004,4917.24,N,12309.57,W,001.3,052.5,000.5,V*20
//where:
//           RMB          Recommended minimum navigation information
//           A            Data status A = OK, V = Void (warning)
//           0.66,L       Cross-track error (nautical miles, 9.99 max),
//                                steer Left to correct (or R = right)
//           003          Origin waypoint ID
//           004          Destination waypoint ID
//           4917.24,N    Destination waypoint latitude 49 deg. 17.24 min. N
//           12309.57,W   Destination waypoint longitude 123 deg. 09.57 min. W
//           001.3        Range to destination, nautical miles (999.9 max)
//           052.5        True bearing to destination
//           000.5        Velocity towards destination, knots
//           V            Arrival alarm  A = arrived, V = not arrived
//           *20          checksum

TCHAR  szTmp[256];
/*
extern START_POINT StartPoints[];
extern TASK_POINT Task[];
extern TASKSTATS_POINT TaskStats[];
extern WAYPOINT *WayPointList;
extern WPCALC   *WayPointCalc;
*/
//WayPointCalc->
  int overindex = GetOvertargetIndex();
  if (!ValidWayPoint(overindex)) return TRUE;

  _stprintf(
      szTmp,
      TEXT("$GPRMB,A,0.66,L,EDLG,%6s,%010.5f,N,%010.5f,E,%05.1f,%05.1f,%05.1f,V"),

      WayPointList[overindex].Name,
      WayPointList[overindex].Latitude * 100,
      WayPointList[overindex].Longitude * 100,
      WayPointCalc[0].Distance * 1000 * TONAUTICALMILES, WayPointCalc[0].Bearing,
      WayPointCalc[0].VGR * TOKNOTS);

  //  _stprintf(szTmp, TEXT("$GPRMB,A,0.00,L,KLE,UWOE,4917.24,N,12309.57,E,011.3,052.5,000.5,V"));
  LX16xxNMEAddCheckSumStrg(szTmp);

  d->Com->WriteString(szTmp);


return(true);
}
Exemplo n.º 2
0
// return current overtarget waypoint name with leading identifier, even if empty
// exception for TEAM MATE: always report OWN CODE if available
void GetOvertargetName(TCHAR *overtargetname) {
  int index;
  if (OvertargetMode == OVT_MATE) {
	if (ValidWayPoint(TeamCodeRefWaypoint)) {
		if (TeammateCodeValid)
			_stprintf(overtargetname,_T("%s> %s"), GetOvertargetHeader(),CALCULATED_INFO.OwnTeamCode);
		else
			_stprintf(overtargetname,_T("%s: %s"), GetOvertargetHeader(),CALCULATED_INFO.OwnTeamCode);
	} else
		_stprintf(overtargetname,_T("%s ---"),GetOvertargetHeader());
	return;
  }
  index=GetOvertargetIndex();
  if (index<0)
	_stprintf(overtargetname,_T("%s ---"),GetOvertargetHeader());
  else 
	_stprintf(overtargetname,_T("%s%s"), GetOvertargetHeader(),WayPointList[index].Name);
}
Exemplo n.º 3
0
void MapWindow::DrawBearing(HDC hdc, const RECT rc)
{
  int overindex=GetOvertargetIndex();
  if (overindex<0) return;

  double startLat = DrawInfo.Latitude;
  double startLon = DrawInfo.Longitude;
  double targetLat;
  double targetLon;

  if (OvertargetMode>OVT_TASK) {
    LockTaskData();
    targetLat = WayPointList[overindex].Latitude;
    targetLon = WayPointList[overindex].Longitude;
    UnlockTaskData();
    DrawGreatCircle(hdc, startLon, startLat, targetLon, targetLat, rc);
  }
  else {
    if (!ValidTaskPoint(ActiveWayPoint)) {
      return; 
    }
    LockTaskData();

    if (AATEnabled && ( DoOptimizeRoute() || ((ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1))) ) {
      targetLat = Task[ActiveWayPoint].AATTargetLat;
      targetLon = Task[ActiveWayPoint].AATTargetLon; 
    } else {
      targetLat = WayPointList[Task[ActiveWayPoint].Index].Latitude;
      targetLon = WayPointList[Task[ActiveWayPoint].Index].Longitude; 
    }
    UnlockTaskData();

    DrawGreatCircle(hdc, startLon, startLat, targetLon, targetLat, rc);

    if (mode.Is(Mode::MODE_TARGET_PAN)) {
      // Draw all of task if in target pan mode
      startLat = targetLat;
      startLon = targetLon;

      LockTaskData();
      for (int i=ActiveWayPoint+1; i<MAXTASKPOINTS; i++) {
        if (ValidTaskPoint(i)) {

          if (AATEnabled && ValidTaskPoint(i+1)) {
            targetLat = Task[i].AATTargetLat;
            targetLon = Task[i].AATTargetLon; 
          } else {
            targetLat = WayPointList[Task[i].Index].Latitude;
            targetLon = WayPointList[Task[i].Index].Longitude; 
          }
       
          DrawGreatCircle(hdc, startLon, startLat,
                          targetLon, targetLat, rc);

          startLat = targetLat;
          startLon = targetLon;
        }
      }
      UnlockTaskData();
    }
  }

  if (AATEnabled) {
    // draw symbol at target, makes it easier to see
    LockTaskData();
    if(mode.Is(Mode::MODE_TARGET_PAN)) {
      for(int i=ActiveWayPoint+1; i<MAXTASKPOINTS; i++) {
        if(ValidTaskPoint(i) && ValidTaskPoint(i+1)) {
          if(i>= ActiveWayPoint) {
            POINT sct;
            LatLon2Screen(Task[i].AATTargetLon, 
                          Task[i].AATTargetLat, 
                          sct);
            DrawBitmapIn(hdc, sct, hBmpTarget,true);
          }
        }
      }
    }
    if(ValidTaskPoint(ActiveWayPoint+1) && (DoOptimizeRoute() || (ActiveWayPoint>0)) ) {
      POINT sct;
      LatLon2Screen(Task[ActiveWayPoint].AATTargetLon, 
                    Task[ActiveWayPoint].AATTargetLat, 
                    sct);
      DrawBitmapIn(hdc, sct, hBmpTarget,true);
    }
    UnlockTaskData();
  }
}
Exemplo n.º 4
0
bool  DevLXV7_EXP::PutGPRMB(PDeviceDescriptor_t d)
{

//RMB - The recommended minimum navigation sentence is sent whenever a route or a goto is active.
//      On some systems it is sent all of the time with null data.
//      The Arrival alarm flag is similar to the arrival alarm inside the unit and can be decoded to
//      drive an external alarm.
//      Note: the use of leading zeros in this message to preserve the character spacing.
//      This is done, I believe, because some autopilots may depend on exact character spacing.
//
//     $GPRMB,A,0.66,L,003,004,4917.24,N,12309.57,W,001.3,052.5,000.5,V*20
//where:
//           RMB          Recommended minimum navigation information
//           A            Data status A = OK, V = Void (warning)
//           0.66,L       Cross-track error (nautical miles, 9.99 max),
//                                steer Left to correct (or R = right)
//           003          Origin waypoint ID
//           004          Destination waypoint ID
//           4917.24,N    Destination waypoint latitude 49 deg. 17.24 min. N
//           12309.57,W   Destination waypoint longitude 123 deg. 09.57 min. W
//           001.3        Range to destination, nautical miles (999.9 max)
//           052.5        True bearing to destination
//           000.5        Velocity towards destination, knots
//           V            Arrival alarm  A = arrived, V = not arrived
//           *20          checksum
static int old_overindex = -99;
static int old_overmode = -99;
int overindex = GetOvertargetIndex();
int overmode  = OvertargetMode;

bool bTaskpresent = false; //ValidTaskPoint(0);
if(bTaskpresent)
  if(ValidTaskPoint(ActiveWayPoint))
    overindex = Task[ActiveWayPoint].Index;


#define SEND_ON_CHANGE_ONLY
#ifdef SEND_ON_CHANGE_ONLY
if(overindex < 0)               /* vaslid waypoint */
  return -1;
if(overindex == old_overindex)  /* same as before */
  if(overmode == old_overmode)  /* and same mode  */
    return 0;
#endif

old_overindex = overindex;
old_overmode  = overmode;
TCHAR  szTmp[512];


int DegLat, DegLon;
double MinLat, MinLon;
char NoS, EoW;

if (!ValidWayPoint(overindex)) return TRUE;

DegLat = (int)WayPointList[overindex].Latitude;
MinLat = WayPointList[overindex].Latitude - DegLat;
NoS = 'N';
if((MinLat<0) || ((MinLat-DegLat==0) && (DegLat<0)))
  {
    NoS = 'S';
    DegLat *= -1; MinLat *= -1;
  }
MinLat *= 60;

DegLon = (int)WayPointList[overindex].Longitude ;
MinLon = WayPointList[overindex].Longitude  - DegLon;
EoW = 'E';
if((MinLon<0) || ((MinLon-DegLon==0) && (DegLon<0)))
  {
    EoW = 'W';
    DegLon *= -1; MinLon *= -1;
  }
MinLon *=60;

#define SET_VALUES_BY_RMB
#ifdef SET_VALUES_BY_RMB
  if(bTaskpresent)
  {
#ifdef NO_RMB_BUT_PLXVTARG
	                     //  $GPRMB,A,0.66,L,003,004 ,4917.24   ,N ,12309.57  ,W ,01.3,52.5,00.5,V*20
    _stprintf( szTmp,  TEXT("$GPRMB,A,0.00,R,XXX,%s%s,%02d%05.2f,%c,%03d%05.2f,%c,%.1f,%.1f,%.1f,V"),
               gettext(TEXT("_@M1323_")), // LKTOKEN _@M1323_ "T>"
	           WayPointList[overindex].Name,
               DegLat, MinLat, NoS, DegLon, MinLon, EoW,
               WayPointCalc[overindex].Distance * TONAUTICALMILES,
               WayPointCalc[overindex].Bearing,
               WayPointCalc[overindex].VGR * TOKNOTS
             );
    LXV7_EXPNMEAddCheckSumStrg(szTmp);
    d->Com->WriteString(szTmp);
#if TESTBENCH
    StartupStore(TEXT("V7: %s"),szTmp);
#endif
#else
    _stprintf( szTmp,  TEXT("$PLXVTARG,%s%s,%02d%05.2f,%c,%03d%05.2f,%c,%i "),
               gettext(TEXT("_@M1323_")), // LKTOKEN _@M1323_ "T>"
	           WayPointList[overindex].Name,
               DegLat, MinLat, NoS, DegLon, MinLon, EoW,
               (int) (WayPointList[overindex].Altitude +0.5)
             );
    LXV7_EXPNMEAddCheckSumStrg(szTmp);
    d->Com->WriteString(szTmp);
#endif
#if TESTBENCH
    StartupStore(TEXT("V7: %s"),szTmp);
#endif

  }
  else
  {                          //  $GPRMB,A,0.66,L,003,004 ,4917.24   ,N ,12309.57  ,W ,01.3,52.5,00.5,V*20
#ifdef NO_RMB_BUT_PLXVTARG
    _stprintf( szTmp,  TEXT("$GPRMB,A,0.00,R,XXX,%s%s,%02d%05.2f,%c,%03d%05.2f,%c,%.1f,%.1f,%.1f,V"),
	           GetOvertargetHeader(),
		       WayPointList[overindex].Name,
	           DegLat, MinLat, NoS, DegLon, MinLon, EoW,
	           WayPointCalc[overindex].Distance * TONAUTICALMILES,
	           WayPointCalc[overindex].Bearing,
	           WayPointCalc[overindex].VGR * TOKNOTS
	         );
	LXV7_EXPNMEAddCheckSumStrg(szTmp);
	d->Com->WriteString(szTmp);
#if TESTBENCH
	StartupStore(TEXT("V7: %s"),szTmp);
#endif
#else
	_stprintf( szTmp,  TEXT("$PLXVTARG,%s%s,%02d%05.2f,%c,%03d%05.2f,%c,%i "),
	           GetOvertargetHeader(),
		       WayPointList[overindex].Name,
	           DegLat, MinLat, NoS, DegLon, MinLon, EoW,
	           (int)(WayPointList[overindex].Altitude +0.5)
	         );
	LXV7_EXPNMEAddCheckSumStrg(szTmp);
	d->Com->WriteString(szTmp);
#endif
#if TESTBENCH
	StartupStore(TEXT("V7: %s"),szTmp);
#endif
  }



#else
  /****************
   * SYm style
   ****************/
  _stprintf( szTmp,  TEXT("$PFLX4,,,,%.f,%.f,,,,0,"),   WayPointCalc[overindex].Distance,  -WayPointCalc[overindex].AltReqd[AltArrivMode]*TOFEET );
  LXV7_EXPNMEAddCheckSumStrg(szTmp);
  d->Com->WriteString(szTmp);
#if TESTBENCH
  StartupStore(TEXT("V7: %s"),szTmp);
#endif

#endif

return(true);
}
Exemplo n.º 5
0
void MapWindow::LKCalculateWaypointReachable(const bool forced)
{
  #if USEONEHZLIMITER
  if (!forced) ONEHZLIMITER;
  #endif

  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

  short numslots=1; // TODO assign numslots with a function, based also on available CPU time

  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
  }


  unsigned int i;
  double waypointDistance, waypointBearing,altitudeRequired,altitudeDifference;

  // LandableReachable is used only by the thermal bar indicator in MapWindow2, after here
  // apparently, is used to tell you if you are below final glide but in range for a landable wp
  // Since nov 2011 we dont user LandableReachable in FinalGlide anymore. 
  // However it is still to be understood what drawbacks we might have by changing calculations here.
  LandableReachable = false;

  if (!WayPointList) return;

  unsigned int scanstart;
  unsigned int scanend;

  #if DEBUGCW
  unsigned int numwpscanned=0;
  #endif

  LockTaskData();

  if (multicalc_slot==0) {
	scanstart=0; // including this
	scanend=NumberOfWayPoints; // will be used -1, so up to this excluded value

	#if DEBUGCW
	StartupStore(_T("... wps=%d multicalc_slot=0 ignored numslot=%d, full scan %d < %d%s"),NumberOfWayPoints,
		numslots,scanstart,scanend,NEWLINE);
	#endif
  } else {
	scanstart=(NumberOfWayPoints/numslots)*(multicalc_slot-1); 
	if (multicalc_slot==numslots)
		scanend=NumberOfWayPoints;
	else
		scanend=scanstart+(NumberOfWayPoints/numslots);

	#if DEBUGCW
	StartupStore(_T("... wps=%d multicalc_slot=%d of %d, scan %d < %d%s"),NumberOfWayPoints,
		multicalc_slot, numslots,scanstart,scanend,NEWLINE);
	#endif
  }

  int overtarg=GetOvertargetIndex();
  if (overtarg<0) overtarg=999999;

  for(i=scanstart;i<scanend;i++) {
    // signed Overtgarget -1 becomes a very high number, casted unsigned
    if ( ( ((WayPointCalc[i].AltArriv[AltArrivMode] >=0)||(WayPointList[i].Visible)) && (WayPointCalc[i].IsLandable || (WayPointList[i].Style==STYLE_THERMAL))) 
	|| WaypointInTask(i) || (i==(unsigned int)overtarg) ) {

	DistanceBearing(DrawInfo.Latitude, DrawInfo.Longitude, WayPointList[i].Latitude, WayPointList[i].Longitude, 
		&waypointDistance, &waypointBearing);

	WayPointCalc[i].Distance=waypointDistance; 
	WayPointCalc[i].Bearing=waypointBearing;

	CalculateGlideRatio(waypointDistance,
		 DerivedDrawInfo.NavAltitude - WayPointList[i].Altitude - GetSafetyAltitude(i));


	altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing, 
						DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0) 
			+ WayPointList[i].Altitude + GetSafetyAltitude(i) - DerivedDrawInfo.EnergyHeight;


	WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired;
	WayPointList[i].AltArivalAGL = DerivedDrawInfo.NavAltitude - altitudeRequired; 
      
	if(WayPointList[i].AltArivalAGL >=0){

		WayPointList[i].Reachable = TRUE;

	  	if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) {
			if ((signed)i!=TASKINDEX) { 
		  		LandableReachable = true;
			}
	  	} else {
			WayPointList[i].Reachable = FALSE;
		}
	} else {
		WayPointList[i].Reachable = FALSE;
	}
	#if DEBUGCW
	numwpscanned++;
	#endif

    } // if landable or in task
  } // for all waypoints

  // This is wrong, because multicalc will not necessarily find the LandableReachable at each pass
  // As of nov 2011 it is better not to change it, and let further investigation after 3.0
  if (!LandableReachable) // indentation wrong here

  for(i=scanstart;i<scanend;i++) {
    if(!WayPointList[i].Visible && WayPointList[i].FarVisible)  {
	// visible but only at a distance (limit this to 100km radius)

	if(  WayPointCalc[i].IsLandable ) {
		#if DEBUGCW
		numwpscanned++;
		#endif

		DistanceBearing(DrawInfo.Latitude, 
                                DrawInfo.Longitude, 
                                WayPointList[i].Latitude, 
                                WayPointList[i].Longitude,
                                &waypointDistance,
                                &waypointBearing);
               
		WayPointCalc[i].Distance=waypointDistance;  // VENTA6
		WayPointCalc[i].Bearing=waypointBearing;

		if (waypointDistance<100000.0) {

			altitudeRequired = GlidePolar::MacCreadyAltitude (GetMacCready(i,0), waypointDistance, waypointBearing,  // 091221
					DerivedDrawInfo.WindSpeed, DerivedDrawInfo.WindBearing, 0,0,true,0)
					+ WayPointList[i].Altitude + GetSafetyAltitude(i);
                  
               		altitudeDifference = DerivedDrawInfo.NavAltitude + DerivedDrawInfo.EnergyHeight - altitudeRequired;                                      
                	WayPointList[i].AltArivalAGL = altitudeDifference;

			WayPointCalc[i].AltReqd[AltArrivMode] = altitudeRequired;

                	if(altitudeDifference >=0){

                	    	WayPointList[i].Reachable = TRUE;

                	    	if (CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, waypointDistance, waypointBearing)) {
                    	 		LandableReachable = true;
                     		} else
                    			WayPointList[i].Reachable = FALSE;
                    	} 
			else { 	
                    		WayPointList[i].Reachable = FALSE;
			}
		} else {
			WayPointList[i].Reachable = FALSE;
		} // <100000

	} // landable wp
     } // visible or far visible
   } // for all waypoint

  UnlockTaskData(); 
  #if DEBUGCW
  StartupStore(_T("...... processed wps: %d\n"),numwpscanned);
  #endif
}
Exemplo n.º 6
0
//
// Called by LKDrawLook8000, this is what happens when we change mapspace mode, advancing through types.
// We paint infopages, nearest, tri, etc.etc.
// Normally there is plenty of cpu available because the map is not even calculated.
// This is why we bring to the Draw thread, in the nearest pages case, also calculations.
//
void MapWindow::DrawMapSpace(HDC hdc,  RECT rc ) {

  HFONT oldfont;
  HBRUSH hB;

  TextInBoxMode_t TextDisplayMode = {0};
  TCHAR Buffer[LKSIZEBUFFERLARGE*2];
#ifdef DRAWLKSTATUS
  bool dodrawlkstatus=false;
#endif

  static POINT p[10];

  if (MapSpaceMode==MSM_WELCOME) {
	if (INVERTCOLORS)
		hB=LKBrush_Petrol;
	  else
		hB=LKBrush_Mlight;
  } else {
	if (INVERTCOLORS)
	  hB=LKBrush_Mdark;
	else
	  hB=LKBrush_Mlight;

  }
  oldfont = (HFONT)SelectObject(hdc, LKINFOFONT); // save font

  if (MapSpaceMode!=MSM_WELCOME) FillRect(hdc,&rc, hB); 

  if (DoInit[MDI_DRAWMAPSPACE]) {
	p[0].x=0; p[0].y=rc.bottom-BottomSize-NIBLSCALE(2); p[1].x=rc.right-1; p[1].y=p[0].y;
	p[2].x=0; p[2].y=0; p[3].x=rc.right-1; p[3].y=0; // 091230 right-1
	p[4].x=0; p[4].y=0; p[5].x=0; p[5].y=rc.bottom-BottomSize-NIBLSCALE(2);
	p[6].x=rc.right-1; p[6].y=0; p[7].x=rc.right-1; p[7].y=rc.bottom-BottomSize-NIBLSCALE(2); // 091230 right-1

//	p[8].x=0; p[8].y=rc.bottom-BottomSize-NIBLSCALE(2); p[9].x=rc.right; p[9].y=p[8].y;

/*
StartupStore(_T("DOINIT DRAWMAPSPACE 21=%d=%d 22=%d=%d 23=%d=%d 24=%d=%d 31=%d=%d 32=%d=%d\n"),
ConfIP[LKMODE_WP][0],ConfIP21,
ConfIP[LKMODE_WP][1],ConfIP22,
ConfIP[LKMODE_WP][2],ConfIP23,
ConfIP[LKMODE_WP][3],ConfIP24,
ConfIP[LKMODE_NAV][0],ConfIP31,
ConfIP[LKMODE_NAV][1],ConfIP32);
*/

	if (MapSpaceMode==MSM_WELCOME) LoadSplash(hdc,_T("LKPROFILE"));
	DoInit[MDI_DRAWMAPSPACE]=false; 
  }

  // Paint borders in green, but only in nearest pages and welcome
  if (MapSpaceMode==MSM_WELCOME || (!IsMultiMap() && MapSpaceMode!=MSM_MAP) )
  {
	  if (INVERTCOLORS) {
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[2], p[3], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[4], p[5], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[6], p[7], RGB_GREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[0], p[1], RGB_GREEN, rc);
	  } else {
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[2], p[3], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[4], p[5], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[6], p[7], RGB_DARKGREEN, rc);
		_DrawLine(hdc, PS_SOLID, NIBLSCALE(1), p[0], p[1], RGB_DARKGREEN, rc);
	  }
  }


#ifdef DRAWLKSTATUS 
  if (LKevent==LKEVENT_NEWRUN) dodrawlkstatus=true;
#endif

  // We are entering mapspacemodes with no initial check on configured subpages.
  // Thus we need to ensure that the page is really available, or find the first valid.
  // However, this will prevent direct customkey access to pages!
  // Instead, we do it when we call next page from InfoPageChange
  // if (!ConfIP[ModeIndex][CURTYPE]) NextModeType();
  switch (MapSpaceMode) {
	case MSM_WELCOME:
#if (1)
		if (!DrawInfo.NAVWarning) { 
		static double firsttime=DrawInfo.Time;
		// delayed automatic exit from welcome mode
		if ( DrawInfo.Time > (firsttime+1.0) ) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			if (EnableSoundModes) LKSound(_T("LK_BEEP1.WAV"));
			RefreshMap();
			break;
		}
		}
#endif
		if(GlobalModelType==MODELTYPE_PNA_MINIMAP)
		{
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}

		DrawWelcome8000(hdc, rc);
		break;
	case MSM_MAPTRK:
		SetSideviewPage(IM_HEADING);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPWPT:
		#if 0
		// If there is no destination, force jump to the map
		if (GetOvertargetIndex()<0) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}
		#endif
		SetSideviewPage(IM_NEXT_WP);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPASP:
		SetSideviewPage(IM_NEAR_AS);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPRADAR:
		LKDrawMultimap_Radar(hdc,rc);
		break;
	case MSM_VISUALGLIDE:
		SetSideviewPage(IM_VISUALGLIDE);
		LKDrawMultimap_Asp(hdc,rc);
		break;
	case MSM_MAPTEST:
		LKDrawMultimap_Test(hdc,rc);
		break;
	case MSM_LANDABLE:
	case MSM_NEARTPS:
	case MSM_AIRPORTS:
		DrawNearest(hdc, rc);
		break;
	case MSM_AIRSPACES:
		DrawAspNearest(hdc, rc);
		break;
	case MSM_COMMON:
	case MSM_RECENT:
		DrawCommon(hdc, rc);
		break;
	case MSM_MAP:
		break;
	case MSM_INFO_THERMAL:
	case MSM_INFO_CRUISE:
	case MSM_INFO_TASK:
	case MSM_INFO_AUX:
	case MSM_INFO_TRI:
	case MSM_INFO_HSI:
	case MSM_INFO_TRF:
	case MSM_INFO_TARGET:
	case MSM_INFO_CONTEST:
		DrawInfoPage(hdc,rc, false);
		break;
	case MSM_TRAFFIC:
		DrawTraffic(hdc,rc);
		break;
	case MSM_THERMALS:
		DrawThermalHistory(hdc,rc);
		break;

  default:
    memset((void*)&TextDisplayMode, 0, sizeof(TextDisplayMode));
    TextDisplayMode.Color = RGB_WHITE;
    TextDisplayMode.NoSetFont = 1; 
    TextDisplayMode.AlligneCenter = 1;
    SelectObject(hdc, LK8TargetFont);
    _stprintf(Buffer,TEXT("MapSpaceMode=%d"),MapSpaceMode);
    TextInBox(hdc, &rc, Buffer, (rc.right-rc.left)/2, NIBLSCALE(50) , 0, &TextDisplayMode, false);
    break;
  }
#ifdef DRAWLKSTATUS
  // no need to clear dodrawlkstatus, it is already reset at each run
  if (dodrawlkstatus) DrawLKStatus(hdc, rc);
#endif
  SelectObject(hdc, oldfont); 
}
Exemplo n.º 7
0
//
// Final Glide Bar, revised for variometer gauge
//
void MapWindow::DrawFinalGlide(HDC hDC, const RECT rc)
{

    SIZE           TextSize;

    if ((GlideBarMode == (GlideBarMode_t)gbDisabled)) {
        GlideBarOffset=0;
        return;
    }

    POINT GlideBar[6] = { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };
    POINT GlideBar0[6] = { {0,0},{9,-9},{18,0},{18,0},{9,0},{0,0} };

    HPEN hpOld;
    HBRUSH hbOld;

    TCHAR Value[10];

    int Offset;
    int Offset0;
    int i;
    int lkVarioOffset=0, minBar, maxBar;

    if (LKVarioBar)
        lkVarioOffset=LKVarioSize+NIBLSCALE(2); //@ 091114

    // 091114
    switch(ScreenSize) {
    case (ScreenSize_t)ss480x234:
    case (ScreenSize_t)ss480x272:
    case (ScreenSize_t)ss720x408:
        minBar=-40;
        maxBar=40;
        break;
    case (ScreenSize_t)ss800x480:
    case (ScreenSize_t)ss400x240:
        minBar=-45;
        maxBar=45;
        break;
    default:
        minBar=-50; // was 60
        maxBar=50;
        break;
    }

    LockTaskData();  // protect from external task changes

    bool invalidbar=false;
#if 101004
    int barindex;
    barindex=GetOvertargetIndex();
    if (barindex>=0) {
#else
    if (ValidTaskPoint(ActiveWayPoint)) {
#endif

        const int y0 = ( (rc.bottom - rc.top )/2)+rc.top;

#if 110609
        if ( ValidTaskPoint(1) && OvertargetMode == OVT_TASK && GlideBarMode == (GlideBarMode_t)gbFinish ) {
            // Before the start, there is no task altitude available!
            if (DerivedDrawInfo.ValidStart) {
                Offset = ((int)DerivedDrawInfo.TaskAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.TaskAltitudeDifference0)/8;
            } else {
                // In this case, print an invalid bar
                invalidbar=true;
                Offset=0;
                Offset0=0;
            }
        } else {
            Offset=(int)WayPointCalc[barindex].AltArriv[AltArrivMode];
            Offset0=Offset;
        }
#else
        // This is wrong, we are painting values relative to MC and ignoring safetyMC
        if (OvertargetMode != OVT_TASK) { //@ 101004
            Offset=(int)WayPointCalc[barindex].AltArriv[AltArrivMode];
            Offset0=Offset;
        } else {
            // 60 units is size, div by 8 means 60*8 = 480 meters.
            if ( (GlideBarMode == (GlideBarMode_t)gbFinish)) {
                Offset = ((int)DerivedDrawInfo.TaskAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.TaskAltitudeDifference0)/8;
            } else {
                Offset = ((int)DerivedDrawInfo.NextAltitudeDifference)/8;
                Offset0 = ((int)DerivedDrawInfo.NextAltitudeDifference0)/8;
            }
        }
#endif

        // TODO feature: should be an angle if in final glide mode

        if(Offset > maxBar) Offset = maxBar;
        if(Offset < minBar) Offset = minBar;
        Offset = IBLSCALE(Offset);
        if(Offset<0) {
            GlideBar[1].y = NIBLSCALE(9);
        }

        if(Offset0 > maxBar) Offset0 = maxBar;
        if(Offset0 < minBar) Offset0 = minBar;
        Offset0 = IBLSCALE(Offset0);
        if(Offset0<0) {
            GlideBar0[1].y = NIBLSCALE(9);
        }

        for(i=0; i<6; i++) {
            GlideBar[i].y += y0;
            // if vario activated
            GlideBar[i].x = IBLSCALE(GlideBar[i].x)+rc.left+lkVarioOffset; //@ 091114
        }
        GlideBar[0].y -= Offset;
        GlideBar[1].y -= Offset;
        GlideBar[2].y -= Offset;

        for(i=0; i<6; i++) {
            GlideBar0[i].y += y0;
            GlideBar0[i].x = IBLSCALE(GlideBar0[i].x)+rc.left+lkVarioOffset; //@ 091114
        }
        GlideBar0[0].y -= Offset0;
        GlideBar0[1].y -= Offset0;
        GlideBar0[2].y -= Offset0;

        if ((Offset<0)&&(Offset0<0)) {
            // both below
            if (Offset0!= Offset) {
                int dy = (GlideBar0[0].y-GlideBar[0].y) +(GlideBar0[0].y-GlideBar0[3].y);
                dy = max(NIBLSCALE(3), dy);
                GlideBar[3].y = GlideBar0[0].y-dy;
                GlideBar[4].y = GlideBar0[1].y-dy;
                GlideBar[5].y = GlideBar0[2].y-dy;

                GlideBar0[0].y = GlideBar[3].y;
                GlideBar0[1].y = GlideBar[4].y;
                GlideBar0[2].y = GlideBar[5].y;
            } else {
                Offset0 = 0;
            }

        } else if ((Offset>0)&&(Offset0>0)) {
            // both above
            GlideBar0[3].y = GlideBar[0].y;
            GlideBar0[4].y = GlideBar[1].y;
            GlideBar0[5].y = GlideBar[2].y;

            if (abs(Offset0-Offset)<NIBLSCALE(4)) {
                Offset= Offset0;
            }
        }

        // draw actual glide bar

        if (Offset<=0) {
            hpOld = (HPEN)SelectObject(hDC, hpFinalGlideBelow);
            hbOld = (HBRUSH)SelectObject(hDC, LKBrush_Red);
        } else {
            hpOld = (HPEN)SelectObject(hDC, hpFinalGlideAbove);
            hbOld = (HBRUSH)SelectObject(hDC, LKBrush_Green);
        }
        Polygon(hDC,GlideBar,6);

        // in case of invalid bar because finish mode with real task but no valid start, we skip
        if (invalidbar) {
            _tcscpy(Value,_T("---"));
            goto _skipout;
        }

        // draw glide bar at mc 0 and X  only for OVT_TASK 101004
        // we dont have mc0 calc ready for other overtargets, not granted at least
        if (OvertargetMode == OVT_TASK) {
            if (Offset0<=0) {
                SelectObject(hDC, hpFinalGlideBelow);
                SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
            } else {
                SelectObject(hDC, hpFinalGlideAbove);
                SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
            }
            if (Offset!=Offset0) {
                Polygon(hDC,GlideBar0,6);
            }


            // Draw an X  on final glide bar if unreachable at current Mc
            if ( (GlideBarMode == (GlideBarMode_t)gbFinish) ) {
                if ((DerivedDrawInfo.TaskTimeToGo>0.9*ERROR_TIME) ||
                        ((MACCREADY<0.01) && (DerivedDrawInfo.TaskAltitudeDifference<0))) {
                    SelectObject(hDC, LKPen_White_N2);
                    POINT Cross[4] = { {-5, -5}, { 5,  5}, {-5,  5}, { 5, -5} };
                    for (i=0; i<4; i++) {
                        Cross[i].x = IBLSCALE(Cross[i].x+9)+lkVarioOffset; //@ 091114
                        Cross[i].y = IBLSCALE(Cross[i].y+9)+y0;
                    }
                    Polygon(hDC,Cross,2);
                    Polygon(hDC,&Cross[2],2);
                }
            } else {
                if ((MACCREADY<0.01) && (DerivedDrawInfo.NextAltitudeDifference<0)) {
                    SelectObject(hDC, LKPen_White_N2);
                    POINT Cross[4] = { {-5, -5}, { 5,  5}, {-5,  5}, { 5, -5} };
                    for (i=0; i<4; i++) {
                        Cross[i].x = IBLSCALE(Cross[i].x+9)+lkVarioOffset;
                        Cross[i].y = IBLSCALE(Cross[i].y+9)+y0;
                    }
                    Polygon(hDC,Cross,2);
                    Polygon(hDC,&Cross[2],2);
                }
            }
        }

        // draw boxed value in the center
        if (OvertargetMode == OVT_TASK ) { //@ 101004
            // A task is made of at least 2 tps, otherwise its a goto
            if (( (GlideBarMode == (GlideBarMode_t)gbFinish) && ValidTaskPoint(1)) ) {
                if(ISPARAGLIDER && DerivedDrawInfo.TaskAltitudeDifference > 0.0) {
                    if ( (ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeArrival) <ALTDIFFLIMIT) //@ 091114
                        _stprintf(Value,TEXT(" --- "));
                    else
                        _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeArrival);
                } else {
                    if ( (ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeDifference) <ALTDIFFLIMIT) //@ 091114
                        _stprintf(Value,TEXT(" --- "));
                    else
                        _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.TaskAltitudeDifference);
                }
            } else {
                if ( (ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]) < ALTDIFFLIMIT)
                    _stprintf(Value,TEXT(" --- "));
                else
                    _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]);
                /*
                 * Well this was the reason why the glidebar value was out of sync with overlays
                if ( (ALTITUDEMODIFY*DerivedDrawInfo.NextAltitudeDifference) < ALTDIFFLIMIT) //@ 091114
                	_stprintf(Value,TEXT(" --- "));
                else
                	_stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*DerivedDrawInfo.NextAltitudeDifference);
                */
            }
        } else {
            if ( (ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]) < ALTDIFFLIMIT)
                _stprintf(Value,TEXT(" --- "));
            else
                _stprintf(Value,TEXT("%1.0f "), ALTITUDEMODIFY*WayPointCalc[barindex].AltArriv[AltArrivMode]);
        }

_skipout:
        // in case of invalidbar we get here with Offset 0

        if (Offset>=0) {
            Offset = GlideBar[2].y+Offset+NIBLSCALE(5);
        } else {
            if (Offset0>0) {
                Offset = GlideBar0[1].y-NIBLSCALE(15);
            } else {
                Offset = GlideBar[2].y+Offset-NIBLSCALE(15);
            }
        }
        // VENTA10
        GetTextExtentPoint(hDC, Value, _tcslen(Value), &TextSize);
        GlideBarOffset=max(NIBLSCALE(11),(int)TextSize.cx) - NIBLSCALE(2);

        TextInBoxMode_t TextInBoxMode = {0};
        TextInBoxMode.Border = true;          //={1|8};
        TextInBoxMode.Reachable = true;
        // boxed numbers are a bit too much on the left, so increase the offset
        TextInBox(hDC, &rc,Value, lkVarioOffset+NIBLSCALE(1), (int)Offset, 0, &TextInBoxMode); //@ 091114

        SelectObject(hDC, hbOld);
        SelectObject(hDC, hpOld);
    } else GlideBarOffset=0; 	// 091125 BUGFIX glidebaroffset is zero when no task point
    {
        UnlockTaskData();
    }

}
Exemplo n.º 8
0
//
// Called by LKDrawLook8000, this is what happens when we change mapspace mode, advancing through types.
// We paint infopages, nearest, tri, etc.etc.
// Normally there is plenty of cpu available because the map is not even calculated.
// This is why we bring to the Draw thread, in the nearest pages case, also calculations.
//
void MapWindow::DrawMapSpace(LKSurface& Surface,  const RECT& rc) {

  BrushReference hB;

  TextInBoxMode_t TextDisplayMode = {0};
  TCHAR Buffer[LKSIZEBUFFERLARGE*2];
#ifdef DRAWLKSTATUS
  bool dodrawlkstatus=false;
#endif


#ifndef DITHER
  if (MapSpaceMode==MSM_WELCOME) {
	if (INVERTCOLORS)
		hB=LKBrush_Petrol;
	  else
		hB=LKBrush_Mlight;
  } else {
	if (INVERTCOLORS)
	  hB=LKBrush_Mdark;
	else
	  hB=LKBrush_Mlight;

  }
#else
  if (INVERTCOLORS)
      hB=LKBrush_Black;
  else
      hB=LKBrush_White;
#endif

  const auto oldfont = Surface.SelectObject(LKINFOFONT); // save font
  if (MapSpaceMode==MSM_WELCOME) {
      LKBitmap WelcomeBitmap = LoadSplash(_T("LKPROFILE"));
      if(WelcomeBitmap) {
          DrawSplash(Surface, WelcomeBitmap);
      }
  } else {
      Surface.FillRect(&rc, hB);
  }

  // Paint borders in green, but only in nearest pages and welcome, and not in DITHER mode
  // In case we want it in dithered mode, some changes are ready to be used.
  #ifndef DITHER
  if (MapSpaceMode==MSM_WELCOME || (!IsMultiMap() && MapSpaceMode!=MSM_MAP) )
  {
     #ifdef DITHER
     LKPen BorderPen(PEN_SOLID, ScreenThinSize, INVERTCOLORS?RGB_WHITE:RGB_BLACK);
     #else
     LKPen BorderPen(PEN_SOLID, ScreenThinSize, INVERTCOLORS?RGB_GREEN:RGB_DARKGREEN);
     #endif
     auto OldPen = Surface.SelectObject(BorderPen);
     auto OldBrush = Surface.SelectObject(LK_HOLLOW_BRUSH);

     Surface.Rectangle(rc.left, rc.top, rc.right, rc.bottom - BottomSize);

     Surface.SelectObject(OldPen);
     Surface.SelectObject(OldBrush);
  }
  #endif


#ifdef DRAWLKSTATUS
  if (LKevent==LKEVENT_NEWRUN) dodrawlkstatus=true;
#endif

  // We are entering mapspacemodes with no initial check on configured subpages.
  // Thus we need to ensure that the page is really available, or find the first valid.
  // However, this will prevent direct customkey access to pages!
  // Instead, we do it when we call next page from InfoPageChange
  // if (!ConfIP[ModeIndex][CURTYPE]) NextModeType();
  switch (MapSpaceMode) {
	case MSM_WELCOME:
#if 0
		SetModeType(LKMODE_MAP,MP_MOVING);
		RefreshMap();
		break;
#endif
#if (1)
		if (!DrawInfo.NAVWarning) {
		static double firsttime=DrawInfo.Time;
		// delayed automatic exit from welcome mode
		if ( DrawInfo.Time > (firsttime+3.0) ) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			LKSound(_T("LK_BEEP1.WAV"));
			RefreshMap();
			break;
		}
		}
#endif
		if(GlobalModelType==MODELTYPE_PNA_MINIMAP)
		{
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}

		DrawWelcome8000(Surface, rc);
		break;
	case MSM_MAPTRK:
		SetSideviewPage(IM_HEADING);
		LKDrawMultimap_Asp(Surface,rc);
		break;
	case MSM_MAPWPT:
		#if 0
		// If there is no destination, force jump to the map
		if (GetOvertargetIndex()<0) {
			SetModeType(LKMODE_MAP,MP_MOVING);
			LKevent=LKEVENT_NONE;
			break;
		}
		#endif
		SetSideviewPage(IM_NEXT_WP);
		LKDrawMultimap_Asp(Surface,rc);
		break;
	case MSM_MAPASP:
		SetSideviewPage(IM_NEAR_AS);
		LKDrawMultimap_Asp(Surface,rc);
		break;
	case MSM_MAPRADAR:
		LKDrawMultimap_Radar(Surface,rc);
		break;
	case MSM_VISUALGLIDE:
		SetSideviewPage(IM_VISUALGLIDE);
		LKDrawMultimap_Asp(Surface,rc);
		break;
	case MSM_MAPTEST:
		LKDrawMultimap_Test(Surface,rc);
		break;
	case MSM_LANDABLE:
	case MSM_NEARTPS:
	case MSM_AIRPORTS:
	case MSM_COMMON:
	case MSM_RECENT:
	case MSM_AIRSPACES:
	case MSM_THERMALS:
	case MSM_TRAFFIC:
		DrawNearest(Surface, rc);
		break;
	case MSM_MAP:
		break;
	case MSM_INFO_THERMAL:
	case MSM_INFO_CRUISE:
	case MSM_INFO_TASK:
	case MSM_INFO_AUX:
	case MSM_INFO_TRI:
	case MSM_INFO_HSI:
	case MSM_INFO_TRF:
	case MSM_INFO_TARGET:
	case MSM_INFO_CONTEST:
		DrawInfoPage(Surface,rc, false);
		break;

  default:
    memset((void*)&TextDisplayMode, 0, sizeof(TextDisplayMode));
    TextDisplayMode.Color = RGB_WHITE;
    TextDisplayMode.NoSetFont = 1;
    TextDisplayMode.AlligneCenter = 1;
    Surface.SelectObject(LK8TargetFont);
    _stprintf(Buffer,TEXT("MapSpaceMode=%d"),MapSpaceMode);
    TextInBox(Surface, &rc, Buffer, (rc.right+rc.left)/2, NIBLSCALE(50) , &TextDisplayMode, false);
    break;
  }
#ifdef DRAWLKSTATUS
  // no need to clear dodrawlkstatus, it is already reset at each run
  if (dodrawlkstatus) DrawLKStatus(hdc, rc);
#endif
  Surface.SelectObject(oldfont);
}