void simpleETE(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int i) {
   if (Basic->Speed <1 || !Calculated->Flying || Calculated->Circling) {
       return;
   }
   #if BUGSTOP
   LKASSERT(ValidWayPoint(i));
   #endif
   if (!ValidWayPoint(i)) return;

   WayPointCalc[i].NextETE= WayPointCalc[i].Distance / Basic->Speed;
}
Example #2
0
void MapWindow::SetPanTaskEdit(unsigned TskPoint) {
    LockTaskData();
    if (ValidTaskPointFast(TskPoint)) {

        MapWindow::Event_Pan(1);

        PanTaskEdit = TskPoint;
        PanLongitude = WayPointList[Task[PanTaskEdit].Index].Longitude;
        PanLatitude = WayPointList[Task[PanTaskEdit].Index].Latitude;

        if ((mode.Is(Mode::MODE_PAN)) || (mode.Is(Mode::MODE_TARGET_PAN))) {
            {
                if (Task[PanTaskEdit].Index != RESWP_PANPOS) {
                    RealActiveWaypoint = Task[PanTaskEdit].Index;
                    LKASSERT(ValidWayPoint(Task[PanTaskEdit].Index));
                    WayPointList[RESWP_PANPOS].Latitude =
                            WayPointList[RealActiveWaypoint].Latitude;
                    WayPointList[RESWP_PANPOS].Longitude =
                            WayPointList[RealActiveWaypoint].Longitude;
                    WayPointList[RESWP_PANPOS].Altitude =
                            WayPointList[RealActiveWaypoint].Altitude;

                    Task[PanTaskEdit].Index = RESWP_PANPOS;
                    RefreshMap();
                }
            }
        }
    }
    UnlockTaskData();
}
Example #3
0
// VENTA3 Alternate destinations
TCHAR *FormatterAlternate::RenderTitle(int *color) {
  
  LockTaskData();
  if(ValidWayPoint(ActiveAlternate))
    {
      if ( DisplayTextType == DISPLAYFIRSTTHREE)
        {
          _tcsncpy(Text,WayPointList[ActiveAlternate].Name,3);
          Text[3] = '\0';
        }
      else if( DisplayTextType == DISPLAYNUMBER)
        {
          _stprintf(Text,TEXT("%d"),
		    WayPointList[ActiveAlternate].Number );
        }
      else
        {
          _tcsncpy(Text,WayPointList[ActiveAlternate].Name,
                   (sizeof(Text)/sizeof(TCHAR))-1);
          Text[(sizeof(Text)/sizeof(TCHAR))-1] = '\0';
        }
    }
  else
    {
      Valid = false;
      RenderInvalid(color);
    }
  UnlockTaskData();

  return(Text);
}
Example #4
0
static void OnPassiveButton(WndButton* pWnd){
  if (HoldOff ==0)
  {
   int res = dlgWayPointSelect(0, 90.0, 1,3);
//   LKASSERT(res>=0);
//   LKASSERT(ValidWayPointFast(res));
   if(res > RESWP_END )
     if(ValidWayPoint(res)) 
    {
      double Frequency = StrToDouble(WayPointList[res].Freq,NULL);
      if(Frequency < 100.0)
      {
     //    DoStatusMessage(_T("No valid Frequency!") );
        return;
      }
      devPutFreqStandby(devA(), Frequency, WayPointList[res].Name);
      devPutFreqStandby(devB(), Frequency, WayPointList[res].Name);

      _stprintf(RadioPara.PassiveName,_T("%s"), WayPointList[res].Name);
      RadioPara.PassiveFrequency = Frequency;
      PassiveRadioIndex = res;
    }
    OnUpdate();
    HoldOff = HOLDOFF_TIME;
  }
}
Example #5
0
void GotoWaypoint(const int wpnum) {
  if (!ValidWayPoint(wpnum)) {
	DoStatusMessage(_T("ERR-639 INVALID GOTO WPT"));
	return;
  }
  if (ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) {
	TCHAR wpname[NAME_SIZE+1];
	_tcscpy(wpname,WayPointList[wpnum].Name);
	wpname[10] = '\0';

	if (MessageBoxX(
	// LKTOKEN  _@M158_ = "CONFIRM GOTO, ABORTING TASK?" 
	gettext(TEXT("_@M158_")),
	// LKTOKEN  _@M40_ = "A task is running!" 
	gettext(TEXT("_@M40_")),
	mbYesNo) == IdYes) {
		LockTaskData();
		FlyDirectTo(wpnum);
		OvertargetMode=OVT_TASK;
		UnlockTaskData();
        }
  } else {
	LockTaskData();
	FlyDirectTo(wpnum);
	OvertargetMode=OVT_TASK;
	UnlockTaskData();
  }
}
Example #6
0
void dlgTeamCodeShowModal(void)
{
    WndProperty* wp = NULL;
    WndButton *buttonCode = NULL;
    wf = NULL;
    char filename[MAX_PATH];
    if (InfoBoxLayout::landscape)
    {
        LocalPathS(filename, TEXT("dlgTeamCode_L.xml"));
        wf = dlgLoadFromXML(CallBackTable,

                            filename,
                            hWndMainWindow,
                            TEXT("IDR_XML_TEAMCODE_L"));
        if (!wf) return;
    }
    else
    {
        LocalPathS(filename, TEXT("dlgTeamCode.xml"));
        wf = dlgLoadFromXML(CallBackTable,

                            filename,
                            hWndMainWindow,
                            TEXT("IDR_XML_TEAMCODE"));
        if (!wf) return;
    }

    TCHAR sTmp[32] = { 0 };
    if( WayPointList && ValidWayPoint(TeamCodeRefWaypoint)) {
        // LKTOKEN _@M1230_ "Team Ref.: "
        _tcsncpy(sTmp, gettext(TEXT("_@M1230_")), 20);
        _tcsncat(sTmp, WayPointList[TeamCodeRefWaypoint].Name,10);
    } else {
        // LKTOKEN _@M1231_ "Team code: SET REF!"
        _tcsncpy(sTmp, gettext(TEXT("_@M1231_")), 30);
    }
    wf->SetCaption(sTmp);

    // set event for button
    buttonCode = ((WndButton *)wf->FindByName(TEXT("cmdSetCode")));
    if (buttonCode) {
        buttonCode->SetOnClickNotify(OnCodeClicked);
    }

    // Set unit for range
    wp = (WndProperty*)wf->FindByName(TEXT("prpRange"));
    if (wp) {
        wp->GetDataField()->SetUnits(Units::GetDistanceName());
    }

    Update();

    wf->SetTimerNotify(OnTimerNotify);

    wf->ShowModal();

    delete wf;
    wf=NULL;

}
Example #7
0
void DoNearestAlternate(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int AltWaypoint) { 

  #if BUGSTOP
  LKASSERT(ValidWayPoint(AltWaypoint));
  #endif
  if (!ValidWayPoint(AltWaypoint)) return;

  double *altwp_gr	= &WayPointCalc[AltWaypoint].GR;
  double *altwp_arrival	= &WayPointCalc[AltWaypoint].AltArriv[AltArrivMode];

  *altwp_gr = CalculateGlideRatio( WayPointCalc[AltWaypoint].Distance,
	Calculated->NavAltitude - WayPointList[AltWaypoint].Altitude - GetSafetyAltitude(AltWaypoint));

  *altwp_arrival = CalculateWaypointArrivalAltitude(Basic, Calculated, AltWaypoint);

  WayPointCalc[AltWaypoint].VGR = GetVisualGlideRatio(*altwp_arrival, *altwp_gr);
}
Example #8
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// Fills out decl->Task data.
///
/// @param lkDecl      LK task declaration data
/// @param decl        task declaration data for device
/// @param errBufSize  error message buffer size
/// @param errBuf[]    [out] error message
///
/// @retval true  declaration successfully filled out
/// @retval false error (description in @p errBuf)
///
//static
bool DevLXNano::FillTask(const Declaration_t& lkDecl, Decl& decl, unsigned errBufSize, TCHAR errBuf[])
{
  // to declared Start, TPs, and Finish we will add Takeoff and Landing,
  // so maximum NB of declared TPs is Decl::max_wp_count - 2
  if (!CheckWPCount(lkDecl,
      Decl::min_wp_count - 2, Decl::max_wp_count - 2, errBufSize, errBuf))
    return(false);

  int wpCount = lkDecl.num_waypoints;

  Decl::Task& task = decl.task;

  if (!GPS_INFO.NAVWarning && GPS_INFO.SatellitesUsed > 0 &&
    GPS_INFO.Day >= 1 && GPS_INFO.Day <= 31 && GPS_INFO.Month >= 1 && GPS_INFO.Month <= 12)
  {
    task.di = GPS_INFO.Day;
    task.mi = GPS_INFO.Month;
    task.yi = GPS_INFO.Year % 100;
  }
  else
  { // use system time
    time_t sysTime = time(NULL);
    tm tm_temp = {0};
    struct tm* utc = gmtime_r(&sysTime, &tm_temp);

    task.di = utc->tm_mday;
    task.mi = utc->tm_mon + 1;
    task.yi = utc->tm_year % 100;
  }

  task.input_time = 0;

  task.fd = task.di;
  task.fm = task.mi;
  task.fy = task.yi;

  task.taskid = 1; // unused, so default is 1

  task.num_of_tp = (char) wpCount - 2; // minus Start and Finish

  // add Start, TPs, and Finish
  for (int i = 0; i < wpCount; i++)
    decl.SetWaypoint(lkDecl.waypoint[i], Decl::tp_regular, i + 1);

  // add Home as Takeoff and Landing
  if (HomeWaypoint >= 0 && ValidWayPoint(HomeWaypoint))
  {
    decl.SetWaypoint(&WayPointList[HomeWaypoint], Decl::tp_takeoff, 0);
    decl.SetWaypoint(&WayPointList[HomeWaypoint], Decl::tp_landing, wpCount + 1);
  }
  else
  {
    decl.SetWaypoint(NULL, Decl::tp_takeoff, 0);
    decl.SetWaypoint(NULL, Decl::tp_landing, wpCount + 1);
  }

  return(true);
} // FillTask()
Example #9
0
void RotateOvertarget(void) {

  OvertargetMode++;

  // For PG/HG, skip BALT overtarget if nothing valid. 
  // We assume that this means no landables ever seen around, because
  // the BA function would keep the old one even if invalid.
  if (ISPARAGLIDER && OvertargetMode==OVT_BALT) {
	if (!ValidWayPoint(BestAlternate)) OvertargetMode++;
  }

  if (OvertargetMode==OVT_FLARM) {
	if (!GPS_INFO.FLARM_Available) OvertargetMode++;
  }

  if (OvertargetMode>OVT_ROTATE) {
	OvertargetMode=OVT_TASK;
  }
  #ifndef DISABLEAUDIO
  if (EnableSoundModes) {
	switch(OvertargetMode) {
		case 0:
			PlayResource(TEXT("IDR_WAV_OVERTONE7"));
			break;
		case 1:
			PlayResource(TEXT("IDR_WAV_OVERTONE0"));
			break;
		case 2:
			PlayResource(TEXT("IDR_WAV_OVERTONE1"));
			break;
		case 3:
			PlayResource(TEXT("IDR_WAV_OVERTONE2"));
			break;
		case 4:
			PlayResource(TEXT("IDR_WAV_OVERTONE3"));
			break;
		case 5:
			PlayResource(TEXT("IDR_WAV_OVERTONE4"));
			break;
		case 6:
			PlayResource(TEXT("IDR_WAV_OVERTONE5"));
			break;
		case 7:
			PlayResource(TEXT("IDR_WAV_OVERTONE6"));
			break;
		case 8:
			PlayResource(TEXT("IDR_WAV_OVERTONE7"));
			break;
		default:
			PlayResource(TEXT("IDR_WAV_OVERTONE5"));
			break;
	}
  }
  #endif
  return;

}
Example #10
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);
}
Example #11
0
static void OnSetAlt2Clicked(WndButton* pWnd){
  LockTaskData();
  Alternate2 = SelectedWaypoint;
  RefreshTask();
  UnlockTaskData();
  if (ValidWayPoint(Alternate2))
  	DoStatusMessage(_T("Altern.2="),WayPointList[Alternate2].Name);
  retStatus=4;
  wf->SetModalResult(mrOK);
}
Example #12
0
// I know all of this is terrible, but no time to clean it
void FormatterAlternate::AssignValue(int i) { 
  LockTaskData();
   switch (i) {
	case 67:
		if ( ValidWayPoint(Alternate1) ) Value=WayPointCalc[Alternate1].GR; 
		else Value=INVALID_GR;
		break;
	case 75:
		if ( ValidWayPoint(Alternate1) ) Value=WayPointCalc[Alternate1].AltArriv[AltArrivMode]; 
		else Value=INVALID_DIFF;
		break;
	case 68:
		if ( ValidWayPoint(Alternate2) ) Value=WayPointCalc[Alternate2].GR; 
		else Value=INVALID_GR;
		break;
	case 76:
		if ( ValidWayPoint(Alternate2) ) Value=WayPointCalc[Alternate2].AltArriv[AltArrivMode]; 
		else Value=INVALID_DIFF;
		break;
	case 69:
		if ( ValidWayPoint(BestAlternate)) Value=WayPointCalc[BestAlternate].GR;
		else Value=INVALID_GR;
		break;
	case 77:
		if ( ValidWayPoint(BestAlternate) ) Value=WayPointCalc[BestAlternate].AltArriv[AltArrivMode]; 
		else Value=INVALID_DIFF;
		break;
	default:
		Value=66.6; // something evil to notice..
		break;
   }
 
   Valid=false;
   if (i>= 75) { 
	// arrival altitude values, ALTDIFFLIMIT is GREATER than INVALID_DIFF
	if (Value >ALTDIFFLIMIT) {
		Valid=true;
		_tcscpy(Format, _T("%+2.0f"));
	} else {
		_tcscpy(Format, _T("%+2.0f"));
	}
   } else {
	// GR values, ALTERNATE_MAXGR is ok because INVALID_GR is greater
	   if ((Value < ALTERNATE_MAXVALIDGR) && (Value>0)) {
		Valid = true;
		if (Value >= 100 )
		  {
		    _tcscpy(Format, _T("%1.0f"));
		  }
		else
		  {
		    _tcscpy(Format, _T("%1.1f"));
		  }
	   } 
  }
 
   
   UnlockTaskData();
}
Example #13
0
void EndDeclaration(void)
{
  // TODO bug: this is causing problems with some analysis software
  // maybe it's because the date and location fields are bogus
  char start[] = "C0000000N00000000ELANDING\r\n";

  // Use homewaypoint as default takeoff and landing position. Better than an empty field!
  if (ValidWayPoint(HomeWaypoint)) {
	TCHAR wname[NAME_SIZE+1];
	wsprintf(wname,_T("%s"),WayPointList[HomeWaypoint].Name);
	wname[8]='\0';
	AddDeclaration(WayPointList[HomeWaypoint].Latitude, WayPointList[HomeWaypoint].Longitude, wname);
  } else
  	IGCWriteRecord(start);
}
Example #14
0
TCHAR *FormatterTeamCode::Render(int *color) {

  if(ValidWayPoint(TeamCodeRefWaypoint))
    {
      *color = 0; // black text
       _tcsncpy(Text,CALCULATED_INFO.OwnTeamCode,5);
       Text[5] = '\0';
    }
  else
    {
      RenderInvalid(color);
    }

  return(Text);
}
Example #15
0
void StartDeclaration(int ntp)
{
  // TODO bug: this is causing problems with some analysis software
  // maybe it's because the date and location fields are bogus
  char start[] = "C0000000N00000000ETAKEOFF\r\n";
  char temp[100];

  if (NumLoggerBuffered==0) {
    FirstPoint.Year = GPS_INFO.Year;
    FirstPoint.Month = GPS_INFO.Month;
    FirstPoint.Day = GPS_INFO.Day;
    FirstPoint.Hour = GPS_INFO.Hour;
    FirstPoint.Minute = GPS_INFO.Minute;
    FirstPoint.Second = GPS_INFO.Second;
  }

  // JMW added task start declaration line

  // LGCSTKF013945TAKEOFF DETECTED

  // IGC GNSS specification 3.6.1
  sprintf(temp,
	  "C%02d%02d%02d%02d%02d%02d0000000000%02d\r\n",
	  // DD  MM  YY  HH  MM  SS  DD  MM  YY IIII TT
	  FirstPoint.Day,
	  FirstPoint.Month,
	  FirstPoint.Year % 100,
	  FirstPoint.Hour,
	  FirstPoint.Minute,
	  FirstPoint.Second,
	  ntp-2);

  IGCWriteRecord(temp);
  // takeoff line
  // IGC GNSS specification 3.6.3

  // Use homewaypoint as default takeoff and landing position. Better than an empty field!
  if (ValidWayPoint(HomeWaypoint)) {
	TCHAR wname[NAME_SIZE+1];
	wsprintf(wname,_T("%s"),WayPointList[HomeWaypoint].Name);
	wname[8]='\0';
	AddDeclaration(WayPointList[HomeWaypoint].Latitude, WayPointList[HomeWaypoint].Longitude, wname);
  } else
  	IGCWriteRecord(start);
                               
}
Example #16
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);
}
Example #17
0
static void OnPaintWaypointPicto(WindowControl * Sender, LKSurface& Surface) {
    (void) Sender;
    if (wf) {

        WndFrame *wPicto = ((WndFrame *) wf->FindByName(TEXT("frmWaypointPicto")));
        if (wPicto) {
            const RECT rc = wPicto->GetClientRect();

            MapWindow::DrawWaypointPictoBg(Surface, rc);
            LKASSERT(ValidWayPoint(SelectedWaypoint));
            if (WayPointCalc[SelectedWaypoint].IsLandable) {
                MapWindow::DrawRunway(Surface, &WayPointList[SelectedWaypoint], rc, 4000, true);
            } else {
                MapWindow::DrawWaypointPicto(Surface, rc, &WayPointList[SelectedWaypoint]);
            }
        }
    }
}
Example #18
0
/*
 * Currently even if set for FIVV, colors are not used.
 */
TCHAR *FormatterAlternate::Render(int *color) {
 //int active=ActiveAlternate; REMOVE
  LockTaskData();
  if(Valid && ValidWayPoint(ActiveAlternate)) {
	switch (WayPointCalc[ActiveAlternate].VGR ) {
		case 0:
			// impossible, give a magenta debug color;
			*color = 5; 
			break;
		case 1:
#ifdef FIVV
			*color = 0; // green
#else
			*color = 0; // blue
#endif
			break;
		case 2:
#ifdef FIVV
			*color = 0; // yellow 4
#else
			*color = 0; // normale white
#endif
			break;
		case 3:
			*color = 1; // red
			break;
		default:
			// even more impossible, give debug color magenta
			*color = 5;
			break;
	}

//	Value=WayPointCalc[ActiveAlternate].GR;    BUGFIX 090918

	_stprintf(Text,Format,Value);
  } else {
	Valid = false;
	RenderInvalid(color);
  }
   UnlockTaskData();
   return(Text);
}
Example #19
0
/*
 * Used by Alternates and BestAlternate
 * Colors VGR are used by DrawNearest &c.
 */
void DoAlternates(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int AltWaypoint) {
   CScopeLock(LockTaskData, UnlockTaskData);
   
  #ifdef GTL2
  // If flying an AAT and working on the RESWP_OPTIMIZED waypoint, then use
  // this "optimized" waypoint to store data for the AAT virtual waypoint.

  if ((AltWaypoint == RESWP_OPTIMIZED) && (!ISPARAGLIDER || (AATEnabled && !DoOptimizeRoute()))) {
    WayPointList[RESWP_OPTIMIZED].Latitude  = Task[ActiveWayPoint].AATTargetLat;
    WayPointList[RESWP_OPTIMIZED].Longitude = Task[ActiveWayPoint].AATTargetLon;
    WayPointList[RESWP_OPTIMIZED].Altitude = WayPointList[Task[ActiveWayPoint].Index].Altitude;
	WaypointAltitudeFromTerrain(&WayPointList[RESWP_OPTIMIZED]);
	_stprintf(WayPointList[RESWP_OPTIMIZED].Name, _T("!%s"),WayPointList[Task[ActiveWayPoint].Index].Name);
  }
  #endif

  // handle virtual wps as alternates
  if (AltWaypoint<=RESWP_END) {
	if (!ValidResWayPoint(AltWaypoint)) return;
  } else {
	if (!ValidWayPoint(AltWaypoint)) return;
  }

  double *altwp_dist	= &WayPointCalc[AltWaypoint].Distance;
  double *altwp_gr	= &WayPointCalc[AltWaypoint].GR;
  double *altwp_arrival	= &WayPointCalc[AltWaypoint].AltArriv[AltArrivMode];

  DistanceBearing(WayPointList[AltWaypoint].Latitude, WayPointList[AltWaypoint].Longitude,
                  Basic->Latitude, Basic->Longitude,
                  altwp_dist, NULL);

  *altwp_gr = CalculateGlideRatio( *altwp_dist,
	Calculated->NavAltitude - WayPointList[AltWaypoint].Altitude - GetSafetyAltitude(AltWaypoint));

  // We need to calculate arrival also for BestAlternate, since the last "reachable" could be
  // even 60 seconds old and things may have changed drastically
  *altwp_arrival = CalculateWaypointArrivalAltitude(Basic, Calculated, AltWaypoint);
  
  WayPointCalc[AltWaypoint].VGR = GetVisualGlideRatio(*altwp_arrival, *altwp_gr);
} 
Example #20
0
TCHAR *FormatterDiffTeamBearing::Render(int *color) {

  if(ValidWayPoint(TeamCodeRefWaypoint) && TeammateCodeValid) {
    Valid = true;
    
    Value = CALCULATED_INFO.TeammateBearing -  GPS_INFO.TrackBearing;
    
    if (Value < -180.0)
      Value += 360.0;
    else
      if (Value > 180.0)
        Value -= 360.0;
    
#ifndef __MINGW32__
    if (Value > 1)
      _stprintf(Text, TEXT("%2.0f°»"), Value);
    else if (Value < -1)
      _stprintf(Text, TEXT("«%2.0f°"), -Value);
    else
      _tcscpy(Text, TEXT("«»"));
#else
    if (Value > 1)
      _stprintf(Text, TEXT("%2.0f°»"), Value);
    else if (Value < -1)
      _stprintf(Text, TEXT("«%2.0f°"), -Value);
    else
      _tcscpy(Text, TEXT("«»"));
#endif
    *color = 0;
    
  } else {
    Valid = false;
    RenderInvalid(color);
  }
  
  return(Text);
}
Example #21
0
static void OnActiveButton(WndButton* pWnd){

  if (HoldOff ==0)
  {
    int res = dlgWayPointSelect(0, 90.0, 1, 3);
    if(res > RESWP_END )
    if(ValidWayPoint(res))
    {
      double  Frequency = StrToDouble(WayPointList[res].Freq,NULL);
      if(!ValidFrequency(Frequency))
      {
   // 	DoStatusMessage(_T("No valid Frequency!") );
	return;
      }
      devPutFreqActive(Frequency, WayPointList[res].Name);
      _stprintf(RadioPara.ActiveName,_T("%s"), WayPointList[res].Name);
      RadioPara.ActiveFrequency = Frequency;

      ActiveRadioIndex = res;
    }
    OnUpdate();
    HoldOff = HOLDOFF_TIME;
  }
}
Example #22
0
// Clear PG 
void ClearOptimizedTargetPos() {

	if (!DoOptimizeRoute())
		return;

	LockTaskData();

	WayPointList[RESWP_OPTIMIZED].Latitude=RESWP_INVALIDNUMBER;
	WayPointList[RESWP_OPTIMIZED].Longitude=RESWP_INVALIDNUMBER;
	WayPointList[RESWP_OPTIMIZED].Altitude=RESWP_INVALIDNUMBER;
	// name will be assigned by function dynamically
	_tcscpy(WayPointList[RESWP_OPTIMIZED].Name, _T("OPTIMIZED") );

	for(int i = 0; ValidWayPoint(Task[i].Index); ++i) {
		Task[i].AATTargetLat = WayPointList[Task[i].Index].Latitude;
		Task[i].AATTargetLon = WayPointList[Task[i].Index].Longitude;
        Task[i].AATTargetAltitude = WayPointList[Task[i].Index].Altitude;
		Task[i].AATTargetLocked = false;
	}

	gPGTask.Initialize();

	UnlockTaskData();
}
Example #23
0
void MapWindow::DrawVisualGlide(LKSurface& Surface, const DiagrammStruct& sDia) {

    const RECT& rci = sDia.rc;

    unsigned short numboxrows = 1;

#if BUGSTOP
    LKASSERT(Current_Multimap_SizeY < SIZE4);
#endif
    switch (Current_Multimap_SizeY) {
        case SIZE0:
        case SIZE1:
            numboxrows = 3;
            break;
        case SIZE2:
            numboxrows = 2;
            break;
        case SIZE3:
            numboxrows = 1;
            break;
        case SIZE4:
            return;
        default:
            LKASSERT(0);
            break;
    }

    if (!ScreenLandscape) {
        numboxrows++;
        if (numboxrows > 3) numboxrows = 3;
    }

    TCHAR tmpT[30];

    line1Font = LK8VisualTopFont;
    line2Font = LK8VisualBotFont;
    SIZE textSizeTop, textSizeBot;
    Surface.SelectObject(line1Font);
    _stprintf(tmpT, _T("MMMM"));
    Surface.GetTextSize(tmpT, &textSizeTop);
    Surface.SelectObject(line2Font);
    _stprintf(tmpT, _T("55.5%s 79%s%s "), Units::GetDistanceName(), MsgToken(2179), MsgToken(2183));
    Surface.GetTextSize(tmpT, &textSizeBot);

    // we can cut the waypoint name, but not the value data, so we use the second row of data
    // to size the box for everything.
    maxtSizeX = textSizeBot.cx;

    int a = (rci.right-rci.left) / (textSizeBot.cx+BOXINTERVAL);
    int b = (rci.right-rci.left) - a * (textSizeBot.cx)-(BOXINTERVAL * (a + 1));

    boxSizeX = textSizeBot.cx + (b / (a + 1));
    boxSizeY = textSizeTop.cy + 1; // single line (wp name) + distance from bottombar

    if (numboxrows > 1) {
        boxSizeY += (textSizeBot.cy * (numboxrows - 1)) - NIBLSCALE(2);
        if (numboxrows > 2) boxSizeY -= NIBLSCALE(1);
    }

#if DEBUG_SCR
    StartupStore(_T("boxX=%d boxY=%d  \n"), boxSizeX, boxSizeY);
#endif

#if DEBUG_SCR
    StartupStore(_T("VG AREA LTRB: %d,%d %d,%d\n"), rci.left, rci.top, rci.right, rci.bottom);
#endif

    const auto oldBrush = Surface.SelectObject(LKBrush_White);
    const auto oldPen = Surface.SelectObject(LK_BLACK_PEN);

    BrushReference brush_back;
    if (!INVERTCOLORS) {
        brush_back = LKBrush_Black;
    } else {
        brush_back = LKBrush_Nlight;
    }

    Surface.FillRect(&rci, brush_back);

    POINT center, p1, p2;
    center.y = rci.top + (rci.bottom - rci.top) / 2;
    center.x = rci.left + (rci.right - rci.left) / 2;

    // numSlotX is the number items we can print horizontally.
    unsigned short numSlotX = (rci.right - rci.left) / (boxSizeX + BOXINTERVAL);
    if (numSlotX > MAXBSLOT) numSlotX = MAXBSLOT;
#if BUGSTOP
    LKASSERT(numSlotX > 0);
#endif
    if (numSlotX == 0) return;

    unsigned short boxInterval = ((rci.right - rci.left)-(boxSizeX * numSlotX)) / (numSlotX + 1);
    unsigned short oddoffset = ( (rci.right-rci.left) - (boxSizeX * numSlotX) - boxInterval * (numSlotX + 1)) / 2;

    /*
    #if BUGSTOP
    // not really harmful
    LKASSERT(oddoffset<=boxInterval);
    #endif
     */

#if DEBUG_SCR
    StartupStore(_T("numSlotX=%d ScreenSizeX=%d boxSizeX=%d interval=%d offset=%d\n"), numSlotX, ScreenSizeX, boxSizeX, boxInterval, oddoffset);
#endif

    unsigned int t;

    // The horizontal grid
    unsigned int slotCenterX[MAXBSLOT + 1];
    for (t = 0; t < numSlotX; t++) {
        slotCenterX[t] = (t * boxSizeX) + boxInterval * (t + 1)+(boxSizeX / 2) + oddoffset+rci.left;
#if DEBUG_SCR
        StartupStore(_T("slotCenterX[%d]=%d\n"), t, slotCenterX[t]);
#endif
    }

    // Vertical coordinates of each up/down subwindow, excluding center line
    int upYtop = rci.top;
#if MIDCENTER
    int upYbottom = center.y + (boxSizeY / 2);
    int downYtop = center.y - (boxSizeY / 2);
#else
    int upYbottom = center.y - CENTERYSPACE;
    int downYtop = center.y + CENTERYSPACE;
#endif
    int upSizeY = upYbottom - upYtop - (boxSizeY);
    ;
    int downYbottom = rci.bottom;
    int downSizeY = downYbottom - downYtop - (boxSizeY);
    ;

#if 0
    // Reassign dynamically the vertical scale for each subwindow size
    double vscale = 1000 * (100 - Current_Multimap_SizeY) / 100;
#else
    // Set the vertical range
    double vscale;
    if (Units::GetUserAltitudeUnit() == unFeet)
        vscale = (1000 / TOFEET);
    else
        vscale = 300.0;
#endif



    Surface.SetBackgroundTransparent();

    RECT trc = rci;

    // Top part of visual rect, target is over us=unreachable=red
    trc.top = rci.top;
    trc.bottom = center.y - 1;
    #ifndef DITHER
    RenderSky(Surface, trc, RGB_WHITE, LKColor(150, 255, 150), GC_NO_COLOR_STEPS / 2);
    #else
    RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE, GC_NO_COLOR_STEPS / 2);
    #endif
    // Bottom part, target is below us=reachable=green
    trc.top = center.y + 1;
    trc.bottom = rci.bottom;
    #ifndef DITHER
    RenderSky(Surface, trc, LKColor(255, 150, 150), RGB_WHITE, GC_NO_COLOR_STEPS / 2);
    #else
    RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE,GC_NO_COLOR_STEPS / 2);
    #endif

    // Draw center line
    p1.x = rci.left + 1;
    p1.y = center.y;
    p2.x = rci.right - 1;
    p2.y = center.y;
    Surface.SelectObject(LKPen_Black_N1);
    Surface.DrawSolidLine(p1, p2, rci);

#if DEBUG_SCR
    StartupStore(_T("... Center line: Y=%d\n"), center.y);
#endif

    Surface.SelectObject(line1Font);
    Surface.SelectObject(LKPen_Black_N0);

    ResetVisualGlideGlobals();

    short res = GetVisualGlidePoints(numSlotX);

    if (res == INVALID_VALUE) {
#if DEBUG_DVG
        StartupStore(_T("...... GVGP says not ready, wait..\n"));
#endif
        return;
    }
    if (res == 0) {
#if DEBUG_DVG
        StartupStore(_T("...... GVGP says no data available!\n"));
#endif
        return;
    }

    // Print them all!
    int offset = (boxSizeY / 2) + CENTERYSPACE;

    LKBrush bcolor;
    LKColor rgbcolor, textcolor;
    int wp;

    unsigned short zeroslot = 0;
    double minbrgdiff = 999.0;
    double minabrgdiff = 999.0; // absolute never negative
    for (unsigned short n = 0; n < numSlotX; n++) {
        wp = slotWpIndex[n];
        if (!ValidWayPoint(wp)) {
            // empty slot nothing to print
            continue;
        }
        double brgdiff = WayPointCalc[wp].Bearing - DrawInfo.TrackBearing;
        // this check is worthless
        if (brgdiff < -180.0) {
            brgdiff += 360.0;
        } else {
            if (brgdiff > 180.0) brgdiff -= 360.0;
        }
        double abrgdiff = brgdiff;
        if (abrgdiff < 0) abrgdiff *= -1;

        if (abrgdiff < minabrgdiff) {
            zeroslot = n;
            minabrgdiff = abrgdiff;
            minbrgdiff = brgdiff;
        }
    }

    // Draw vertical line
#define DEGRANGE 10	// degrees left and right to perfect target
    if (minabrgdiff < 1) {
        p1.x = slotCenterX[zeroslot];
    } else {
        // set fullscale range
        if (minabrgdiff > DEGRANGE) {
            minabrgdiff = DEGRANGE;
            if (minbrgdiff < 0)
                minbrgdiff = -1 * DEGRANGE;
            else
                minbrgdiff = DEGRANGE;
        }
        // we shift of course in the opposite direction
        p1.x = slotCenterX[zeroslot]-(int) ((boxSizeX / (DEGRANGE * 2)) * minbrgdiff);
    }
    p2.x = p1.x;

    p1.y = rci.top + 1;
    p2.y = rci.bottom - 1;
    Surface.SelectObject(LKPen_Black_N1);
    Surface.DrawSolidLine(p1, p2, rci);



    for (unsigned short n = 0; n < numSlotX; n++) {

        wp = slotWpIndex[n];
        if (!ValidWayPoint(wp)) {
            // empty slot nothing to print
            continue;
        }
#if DEBUG_DVG
        StartupStore(_T("... DVG PRINT [%d]=%d <%s>\n"), n, wp, WayPointList[wp].Name);
#endif

        Sideview_VGWpt[n] = wp;

        double altdiff = WayPointCalc[wp].AltArriv[AltArrivMode];
        int ty;
#if DEBUG_SCR
        StartupStore(_T("... wp=<%s>\n"), WayPointList[wp].Name);
#endif

        // Since terrain can be approximated due to low precision maps, or waypoint position or altitude error,
        // we have a common problem: we get an obstacle to get to the waypoint because it is
        // positioned "BELOW" the terrain itself. We try to reduce this problem here.
#define SAFETERRAIN	50

        // Positive arrival altitude for the waypoint, upper window
        if (altdiff >= 0) {
            if (altdiff == 0)altdiff = 1;
            double d = vscale / altdiff;
            if (d == 0) d = 1;
            ty = upYbottom - (int) ((double) upSizeY / d)-(boxSizeY / 2);
#if DEBUG_SCR
            StartupStore(_T("... upYbottom=%d upSizeY=%d / (vscale=%f/altdiff=%f = %f) =- %d  ty=%d  offset=%d\n"),
                    upYbottom, upSizeY, vscale, altdiff, d, (int) ((double) upSizeY / d), ty, offset);
#endif
            if ((ty - offset) < upYtop) ty = upYtop + offset;
            if ((ty + offset) > upYbottom) ty = upYbottom - offset;
#if DEBUG_SCR
            StartupStore(_T("... upYtop=%d upYbottom=%d final ty=%d\n"), upYtop, upYbottom, ty);
#endif


            //
            // This is too confusing. We want simple colors, not shaded
            // rgbcolor = MixColors( LKColor(50,255,50), LKColor(230,255,230),  altdiff/(vscale-50));
            //

            if (altdiff <= SAFETERRAIN) {
                rgbcolor = RGB_LIGHTYELLOW;
            } else {
                if (!CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo,
                        WayPointCalc[wp].Distance, WayPointCalc[wp].Bearing)) {
                    rgbcolor = RGB_LIGHTRED;
                } else {
#ifdef DITHER
                    rgbcolor = RGB_WHITE;
#else
                    rgbcolor = RGB_LIGHTGREEN;
#endif
                }
            }
            bcolor.Create(rgbcolor);

        } else {
            double d = vscale / altdiff;
            if (d == 0) d = -1;
            ty = downYtop - (int) ((double) downSizeY / d)+(boxSizeY / 2); // - because the left part is negative, we are really adding.
            if ((ty - offset) < downYtop) ty = downYtop + offset;
            if ((ty + offset) > downYbottom) ty = downYbottom - offset;

#ifdef DITHER
            rgbcolor = RGB_WHITE; // negative part, no need to render dark
#else
            rgbcolor = RGB_LIGHTRED;
#endif
            bcolor.Create(rgbcolor);
        }

        TCHAR line2[40], line3[40];
        TCHAR value[40], unit[30];
        TCHAR name[NAME_SIZE + 1];
        double ar = (WayPointCalc[wp].AltArriv[AltArrivMode] * ALTITUDEMODIFY);
        _tcscpy(name, WayPointList[wp].Name);
        CharUpper(name);

        if (IsSafetyAltitudeInUse(wp))
            textcolor = RGB_DARKBLUE;
        else
            textcolor = RGB_BLACK;

        switch (numboxrows) {
            case 0:
#if BUGSTOP
                LKASSERT(0);
#endif
                return;

            case 1:
                // 1 line: waypoint name
                VGTextInBox(Surface, n, 1, name, NULL, NULL, slotCenterX[n], ty, textcolor, bcolor);
                break;

            case 2:
                // 2 lines: waypoint name + altdiff
                LKFormatAltDiff(wp, false, value, unit);
                // Should we print also the GR?
                if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) {
                    if (ar >= -999 && ar <= 999)
                        _stprintf(line2, _T("%s   "), value);
                    else
                        _stprintf(line2, _T("%s  "), value);
                    LKFormatGR(wp, false, value, unit);
                    _tcscat(line2, value);
                } else {
                    _stprintf(line2, _T("%s   ---"), value);
                }

                VGTextInBox(Surface, n, 2, name, line2, NULL, slotCenterX[n], ty, textcolor, bcolor);
                break;

            case 3:
                // 3 lines: waypoint name + dist + altdiff
                LKFormatDist(wp, false, value, unit);
                _stprintf(line2, _T("%s%s"), value, unit);

                LKFormatBrgDiff(wp, false, value, unit);
                _stprintf(tmpT, _T(" %s%s"), value, unit);
                _tcscat(line2, tmpT);

                LKFormatAltDiff(wp, false, value, unit);
                // Should we print also the GR?
                if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) {
                    if (ar >= -999 && ar <= 999)
                        _stprintf(line3, _T("%s   "), value);
                    else
                        _stprintf(line3, _T("%s  "), value);
                    LKFormatGR(wp, false, value, unit);
                    _tcscat(line3, value);
                } else {
                    _stprintf(line3, _T("%s   ---"), value);
                }

                VGTextInBox(Surface, n, 3, name, line2, line3, slotCenterX[n], ty, textcolor, bcolor);
                break;
            default:
#if BUGSTOP
                LKASSERT(0);
#endif
                return;
        }

    } // for numSlotX



    // Cleanup and return
    Surface.SelectObject(oldBrush);
    Surface.SelectObject(oldPen);
    return;
}
Example #24
0
static int OnUpdate(void) {
TCHAR Name[250];

    if((ValidWayPoint(ActiveRadioIndex)) &&0)
    {
        if( ActiveRadioIndex > RESWP_END)
        {
          _stprintf(Name,_T("%s"),WayPointList[ActiveRadioIndex].Name);
          if(wpnewActive)
            wpnewActive->SetCaption(Name);
          _stprintf(Name,_T("%s"),WayPointList[ActiveRadioIndex].Freq);
          if(wpnewActiveFreq)
            wpnewActiveFreq->SetCaption(Name);
        }
    }
    else
    {
        _stprintf(Name,_T("%s"),RadioPara.ActiveName);
        if(wpnewActive)
          wpnewActive->SetCaption(Name);
        _stprintf(Name,_T("%7.3f"),RadioPara.ActiveFrequency);
        if(wpnewActiveFreq)
          wpnewActiveFreq->SetCaption(Name);        
    }


    if((ValidWayPoint(PassiveRadioIndex)) && 0)
    {
        if( PassiveRadioIndex > RESWP_END )        
        {
          _stprintf(Name,_T("%s"),WayPointList[PassiveRadioIndex].Name);
          if(wpnewPassive)
            wpnewPassive->SetCaption(Name);
          _stprintf(Name,_T("%s"),WayPointList[PassiveRadioIndex].Freq);
          if(wpnewPassiveFreq)
            wpnewPassiveFreq->SetCaption(Name);
        }
    }
    else
    {
        _stprintf(Name,_T("%s"),RadioPara.PassiveName);
        if(wpnewPassive)
          wpnewPassive->SetCaption(Name);
        _stprintf(Name,_T("%7.3f"),RadioPara.PassiveFrequency);
        if(wpnewPassiveFreq)
          wpnewPassiveFreq->SetCaption(Name);        
    }


    if(wpnewVol)
    {
        if(VolMode == VOL)   {
           _stprintf(Name,_T("V%i"),lVolume);
           wpnewVol->SetCaption(Name);
        }    else      {
        _stprintf(Name,_T("S%i"),lSquelch);
          wpnewVol->SetCaption(Name);
        }
    }
return 0;
}
Example #25
0
bool DetectFreeFlying(NMEA_INFO *Basic, DERIVED_INFO *Calculated) {

  static bool   ffDetected=false;
  static int    lastMaxAltitude=-1000;
  static double gndAltitude=0;
  static double vario[8];
  static bool   winchdetected=false;
  static short  wlaunch=0;
  static int    altLoss=0;
  static bool   safeTakeoffDetected=false;
  static bool   nowGearWarning = true; // init with true to prevent gear warning just after free flight detect
  static unsigned short noMessages =0;

  bool forcereset=LKSW_ForceFreeFlightRestart;

  if (DoInit[MDI_DETECTFREEFLYING]) {
    for (int i=0; i<8; i++) vario[i]=0;
    gndAltitude=0;
    winchdetected=false;
    wlaunch=0;
    altLoss=0;
    ffDetected=false;
    lastMaxAltitude=-1000;
    safeTakeoffDetected=false;
    nowGearWarning=true; // we are here before freeflight!
    noMessages=0;	// after a new takeoff we can give warnings again!
    DoInit[MDI_DETECTFREEFLYING]=false;
  }

  // reset on ground
  if (Calculated->Flying == false) {
    Calculated->FreeFlying=false;
    ffDetected=false;
    lastMaxAltitude=-1000;
    // For winch launches and also for quick taekoffs do not update gndAltitude when the plane
    // is already moving, probably towed or winched already. Threshold is at 4m/s, = 14kmh
    if (Basic->Speed<=4.0) gndAltitude=Basic->Altitude;
    winchdetected=false;
    wlaunch=0;
    altLoss=FF_TOWING_ALTLOSS;
    safeTakeoffDetected=false;
    LKSW_ForceFreeFlightRestart=false;
    return false;
  }

  if (forcereset) {
	LKSW_ForceFreeFlightRestart=false;
	#if TESTBENCH
	StartupStore(_T("... Forced FreeFlight Restart!\n"));
	#endif
	DoStatusMessage(MsgToken(1452),NULL,false);  // LKTOKEN  _@M1452_ = "Free flight detected"
	goto confirmbacktrue;
  }

  //  If we have a takeoff alarm, and  it is still pending!
  //  The AlarmTakeoffSafety is saved multiplied by 1000, so conversion between feet and meters will always be
  //  accurate and possible with no safety concerns about loosing accuracy on this issue!
  if ( (AlarmTakeoffSafety>0) && !safeTakeoffDetected ) {
	// Only if not in SIMMODE, or in SIM but replaying a flight
	if ( !(SIMMODE && !ReplayLogger::IsEnabled()) ) {
		if ( (Basic->Altitude - gndAltitude)>=(AlarmTakeoffSafety/1000)) {
			LKSound(_T("LK_SAFETAKEOFF.WAV"));
			safeTakeoffDetected=true;
		}
	}
  }

#ifdef  GEAR_WARNING
  if ( (GearWarningMode>0) && ffDetected) {
	// Only if not in SIMMODE, or in SIM but replaying a flight
//	if ( !(SIMMODE && !ReplayLogger::IsEnabled()) )
	  {

		double AltitudeAGL = Calculated->AltitudeAGL;

	    double dist = 0;
	    if(GearWarningMode ==1){
	      if( ValidWayPoint(BestAlternate))
	      {
	         AltitudeAGL = Basic->Altitude - WayPointList[BestAlternate].Altitude; // AGL = height above landable
	         if( AltitudeAGL <= (GearWarningAltitude/1000))
	            DistanceBearing(Basic->Latitude, Basic->Longitude, WayPointList[BestAlternate].Latitude, WayPointList[BestAlternate].Longitude, &dist, NULL);
	      }else{
	    	dist = 9999; // set to far away if best alternate  not valid
	      }
	    }

		if (( AltitudeAGL  <=(GearWarningAltitude/1000)) && (noMessages < MAX_NO_GEAR_WARN))
		{
		  if(!nowGearWarning)
		  {
		    if(dist < 3700) // show gear warning if 2Nautical Miles close to landable
		    {
			  LKSound(_T("LK_GEARWARNING.WAV"));
			  DoStatusMessage(gettext(TEXT("_@M1834_")),NULL,false);  // LKTOKEN _@M1834_ "Prepare for landing !"
			  nowGearWarning=true;
			  noMessages++;

#if TESTBENCH
			  if(GearWarningMode ==2)
			    StartupStore(_T("... %i. Gear warning at %im = %im [%im] AGL%s"),noMessages,(int)Basic->Altitude,(int)AltitudeAGL,(int)GearWarningAltitude/1000,NEWLINE);
			  else
				 StartupStore(_T("...%i. Gear warning at %im = %im [%im] over landable %s (%im)%s"),noMessages,(int)Basic->Altitude,(int)AltitudeAGL,(int)GearWarningAltitude/1000,WayPointList[BestAlternate].Name,(int)WayPointList[BestAlternate].Altitude,NEWLINE);
#endif

		    }
			if (noMessages==MAX_NO_GEAR_WARN) {
				StartupStore(_T("... GOING SILENT on too many Gear warnings.  %s%s"),WhatTimeIsIt(),NEWLINE);

				DoStatusMessage(MsgToken(2304)); // GOING SILENT ON GEAR REPORTING
				noMessages++;	// we go to 11, and never be back here		  }
			}
		  }
		}
		else
		{
		  if(( AltitudeAGL)> ((GearWarningAltitude/1000)+100))  // re-enable warning if higher that 100m above Gear altitude
		  {
            if( nowGearWarning )
            {
#if TESTBENCH
			  if(GearWarningMode ==2)
			    StartupStore(_T("...rearmed %i. Gear warning at %im = %im AGL %s"),noMessages,(int)Basic->Altitude,(int)AltitudeAGL,NEWLINE);
			  else
				 StartupStore(_T("..rearmed %i. Gear warning at %im = %im over landable %s (%im)%s"),noMessages,(int)Basic->Altitude,(int)AltitudeAGL,WayPointList[BestAlternate].Name,(int)WayPointList[BestAlternate].Altitude,NEWLINE);
#endif
	  		  nowGearWarning = false;
            }
		  }
		}
	}
  }
#endif

  if (ISPARAGLIDER) {
    Calculated->FreeFlying=true;
    return true; 
  }
  if (ISGAAIRCRAFT||ISCAR) {
    return false; 
  }

  // do something special for other situations
  if (SIMMODE && !ReplayLogger::IsEnabled()) {
    Calculated->FreeFlying=true;
    ffDetected=true;
    return true; 
  }

  // If flying, and start was already detected, assume valid freeflight.
  // Put here in the future the Engine Noise Detection for motorplanes
  if (ffDetected)
    return true;

  // Here we are flying, and the start of free flight must still be detected

  // In any case, after this time, force a start. This is to avoid that for any reason, no FF is ever detected.
  if ((int)Basic->Time > ( Calculated->TakeOffTime + FF_MAXTOWTIME)) {
    #if DEBUG_DFF
    DoStatusMessage(_T("DFF:  TIMEOUT"));
    #endif
    goto backtrue;	// unconditionally force start FF
  }

 
  // A loss of altitude will trigger FF 
  lastMaxAltitude = std::max(lastMaxAltitude, (int)Basic->Altitude);
  if ((int)Basic->Altitude <= ( lastMaxAltitude - altLoss)) {
    #if DEBUG_DFF
    if ( (winchdetected) || ((Basic->Altitude - gndAltitude)>=400) 
      && ((Basic->Time - Calculated->TakeOffTime) >= 150))
      DoStatusMessage(_T("DFF:  ALTITUDE LOSS"));
    #endif
    goto lastcheck;
  }

#ifdef TOW_CRUISE
  // If circling, we assume that we're in free flight and use the
  // start-of-circling time and position.  Turning.cpp makes sure
  // we aren't circling while on tow by imposing a 12 deg/sec turn
  // rate limit for on-tow turning.
#else
  // If circling we assume that we are in free flight already, using the start of circling time and position.
  // But we must be sure that we are not circling.. while towed. A 12 deg/sec turn rate will make it quite sure.
  // Of course nobody can circle while winchlaunched, so in this case FF is immediately detected.
#endif

#ifdef TOW_CRUISE
  // The 12 deg/sec check is now done in Turning.cpp, so there's no
  // need to do it here, too.  Doing it here, too, could allow the
  // possibility of climb mode engaging without FF detection, if the
  // climb rate goes above 12 deg/sec for just a split second.
  //if (Calculated->Circling && (winchdetected ||
  //   (fabs(Calculated->TurnRate) >= 12))) {

  if (Calculated->Circling) {
#else
  if (Calculated->Circling && ( winchdetected || ( fabs(Calculated->TurnRate) >=12 ) ) ) {
#endif

    if (UseContestEngine()) {
      CContestMgr::Instance().Add(new CPointGPS(static_cast<unsigned>(Calculated->ClimbStartTime),
	Calculated->ClimbStartLat, Calculated->ClimbStartLong,
	static_cast<unsigned>(Calculated->ClimbStartAlt)));
    }

    #if DEBUG_DFF
    DoStatusMessage(_T("DFF:  THERMALLING"));
    #endif
    goto backtrue;
  }

  vario[7]=vario[6];
  vario[6]=vario[5];
  vario[5]=vario[4];
  vario[4]=vario[3];
  vario[3]=vario[2];
  vario[2]=vario[1];
  vario[1]=Calculated->Vario;

  double newavervario;
  double oldavervario;

  newavervario=(vario[1]+vario[2]+vario[3])/3;

  if (newavervario>=10) {
    wlaunch++;
  } else {
    wlaunch=0;
  }
  // After (6+2) 8 seconds of consecutive fast climbing (AFTER TAKEOFF DETECTED!), winch launch is detected
  if (wlaunch==6) {
    #if DEBUG_DFF
    DoStatusMessage(_T("DFF:  WINCH LAUNCH"));
    #endif
    altLoss=FF_WINCHIN_ALTLOSS;
    winchdetected=true;
  }
    
  if (newavervario>0.3)
    return false;

  if (newavervario<=0) {
    #if DEBUG_DFF
    if ( (winchdetected) || ((Basic->Altitude - gndAltitude)>=400) 
      && ((Basic->Time - Calculated->TakeOffTime) >= 150))
      DoStatusMessage(_T("DFF:  VARIO SINK"));
    #endif
    goto lastcheck;
  }

  oldavervario=(vario[4]+vario[5]+vario[6]+vario[7])/4;
  // current avervario between 0.0 and 0.3: uncertain situation,  we check what we had in the previous time
  // Windy situations during towing may lead to false positives if delta is too low. This is the most
  // difficult part which could lead to false positives or negatives.
  if ( oldavervario >=4.5 ) {
    #if DEBUG_DFF
    StartupStore(_T("..... oldavervario=%.1f newavervario=%.1f current=%.1f\n"),oldavervario,newavervario,Calculated->Vario);
    if ( (winchdetected) || ((Basic->Altitude - gndAltitude)>=400) 
      && ((Basic->Time - Calculated->TakeOffTime) >= 150))
      DoStatusMessage(_T("DFF:  DELTA VARIO"));
    #endif
    goto lastcheck;
  }

  // No free flight detected
  return false;

  lastcheck: 

  // Unless under a winch launch, we shall not consider anything below 400m gain, 
  // and before 2.5minutes have passed since takeoff
  // Anybody releasing tow before 3 minutes will be below 500m QFE, and won't go much around
  // until a thermal is found. So no problems. 

  if (!winchdetected) {
    if ( (Basic->Altitude - gndAltitude)<400)
      return false;
    if ( (Basic->Time - Calculated->TakeOffTime) < 150)
      return false;
  }

  backtrue:
  // In real flight on a fly device (assuming a windowsPC is NOT a fly device)
  // give no messages during critical phases of flight
  #if ( !defined(WINDOWSPC) || WINDOWSPC==0 )
  if (SIMMODE)
  #endif
  DoStatusMessage(gettext(TEXT("_@M1452_")),NULL,false);  // LKTOKEN  _@M1452_ = "Free flight detected"

  confirmbacktrue:
  // Always sound
  if (EnableSoundModes) {
	LKSound(_T("LK_FREEFLIGHT.WAV"));
  }

  StartupStore(_T(". Free Flight started %s%s"), WhatTimeIsIt(),NEWLINE);

  ffDetected=true;
  Calculated->FreeFlying=true;
  Calculated->FreeFlightStartTime=Basic->Time;
  Calculated->FreeFlightStartQNH=Basic->Altitude;
  Calculated->FreeFlightStartQFE=gndAltitude;

  WayPointList[RESWP_FREEFLY].Latitude=Basic->Latitude;
  WayPointList[RESWP_FREEFLY].Longitude=Basic->Longitude;
  WayPointList[RESWP_FREEFLY].Altitude=Basic->Altitude;
  if (WayPointList[RESWP_FREEFLY].Altitude==0) WayPointList[RESWP_FREEFLY].Altitude=0.001;
  WayPointList[RESWP_FREEFLY].Reachable=TRUE;
  WayPointList[RESWP_FREEFLY].Visible=TRUE;
  WayPointList[RESWP_FREEFLY].Format = LKW_VIRTUAL;

  TCHAR Temp[30];
  Units::TimeToTextS(Temp, (int)TimeLocal((long)Calculated->FreeFlightStartTime));

  LKASSERT(WayPointList[RESWP_FREEFLY].Comment!=NULL);

  WayPointList[RESWP_FREEFLY].Comment[99]='\0'; // for safety
  _stprintf(WayPointList[RESWP_FREEFLY].Comment,_T("%s: %s  @%.0f%s QNH"),
	gettext(_T("_@M1754_")), 	// Free flight start
	Temp,
	ALTITUDEMODIFY*Calculated->FreeFlightStartQNH,
	Units::GetAltitudeName());

  ResetFreeFlightStats(Calculated);
  return true;

}




//
// Upon FF detection, we reset some calculations, ONLY SOME.
// Most things are pertinent to flying, not to freeflying.
//
// Notice 1:  we cannot do oldstyle reset, because it would reset also takeoff time.
//            For FF, we need new stuff doing new things.
// Notice 2:  GA and CAR mode will not ever use FF stuff
//
// Notice 3:  since FF is not (still) affecting tasks, we shall not reset task values now
//
void ResetFreeFlightStats(DERIVED_INFO *Calculated) {

  int i;

  CContestMgr::Instance().Reset(Handicap);
  flightstats.Reset();

  Calculated->timeCruising = 0;
  Calculated->timeCircling = 0;

  // Calculated->TotalHeightClimb = 0;
  // Calculated->CruiseStartTime = -1;
  // 
  // ClimbStartTime CANNOT be reset here: it is a loop! We use themal start to detect freeflight!
  // We have a conflict here!
  // Calculated->ClimbStartTime = -1;  
  // Calculated->AverageThermal = 0;

  for (i=0; i<200; i++) {
     Calculated->AverageClimbRate[i]= 0;
     Calculated->AverageClimbRateN[i]= 0;
  }
  Calculated->MaxThermalHeight = 0;
  for (i=0; i<NUMTHERMALBUCKETS; i++) {
    Calculated->ThermalProfileN[i]=0;
    Calculated->ThermalProfileW[i]=0;
  }

  // clear thermal sources for first time.
  for (i=0; i<MAX_THERMAL_SOURCES; i++) {
    Calculated->ThermalSources[i].LiftRate= -1.0;
  }

  // The MaxHeightGain function wait for FF in flight and will update
  // considering 0 as a no-altitude-set-yet .
  Calculated->MinAltitude = 0;
  Calculated->MaxAltitude = 0;
  Calculated->MaxHeightGain = 0;


}
Example #26
0
static void OnTaskListEnter(WindowControl * Sender,
		     WndListFrame::ListInfo_t *ListInfo) {
  (void)Sender;
  bool isfinish = false;

  ItemIndex = ListInfo->ItemIndex+ListInfo->ScrollIndex;

  // If we are clicking on Add Waypoint
  if ((ItemIndex>=0) && (ItemIndex == UpLimit) && (UpLimit<MAXTASKPOINTS)) {

	// add new waypoint
	if (CheckDeclaration()) {

		if (ItemIndex>0) {
#ifdef LAST_TASKPOINT_QUESTION
			if (MessageBoxX(
			// LKTOKEN  _@M817_ = "Will this be the finish?"
			MsgToken(817),
			// LKTOKEN  _@M54_ = "Add Waypoint"
			MsgToken(54),
			mbYesNo) == IdYes)
#else
		    if(0)
#endif
			{

				isfinish = true;

				// Set initial wp as the finish by default, or home if nonex
				LockTaskData();
                // ItemIndex is already checked for > 0 no need to test twice
				Task[ItemIndex].Index = Task[0].Index;
				UnlockTaskData();

			} else {
				isfinish = false;
			}
		}

		int res;
		res = dlgWayPointSelect();

		if (ValidWayPoint(res)){

			LockTaskData();
            ResetTaskWaypoint(ItemIndex);
			Task[ItemIndex].Index = res;
            Task[ItemIndex].PGConeBase = WayPointList[res].Altitude;

			UnlockTaskData();
			if (ItemIndex==0) {
				dlgTaskWaypointShowModal(ItemIndex, 0, true); // start waypoint
			} else if (isfinish) {
				dlgTaskWaypointShowModal(ItemIndex, 2, true); // finish waypoint
			} else {
				if (AATEnabled || DoOptimizeRoute()) {
					// only need to set properties for finish
					dlgTaskWaypointShowModal(ItemIndex, 1, true); // normal waypoint
				}
			}

		} // ValidWaypoint
		OverviewRefreshTask();

	} // CheckDeclaration

	return;

  } // Index==UpLimit, clicking on Add Waypoint

  if (ItemIndex<UpLimit) {

	if (ItemIndex==0) {
		dlgTaskWaypointShowModal(ItemIndex, 0); // start waypoint
	} else {
		if (ItemIndex==UpLimit-1) {
			dlgTaskWaypointShowModal(ItemIndex, 2); // finish waypoint
		} else {
			dlgTaskWaypointShowModal(ItemIndex, 1); // turnpoint
		}
	}
	  OverviewRefreshTask();
  }

} // OnTaskListEnter
Example #27
0
// return current overtarget waypoint index, or -1 if not available
int GetOvertargetIndex(void) {
  int index;
  switch (OvertargetMode) {
	case OVT_TASK: // task 
		if ( ValidTaskPoint(ActiveWayPoint) != false ) {
			if (DoOptimizeRoute())
				index=RESWP_OPTIMIZED;
			else {
				index = Task[ActiveWayPoint].Index;
			}
			if ( index >=0 ) return index;
		}
		return -1;
		break;
	case OVT_ALT1: // alternate 1
		if ( ValidWayPoint(Alternate1) != false ) {
			index = Alternate1;
			if ( index >=0 ) return index;
		}
		return -1;
		break;
	case OVT_ALT2: // alternate 2
		if ( ValidWayPoint(Alternate2) != false ) {
			index = Alternate2;
			if ( index >=0 ) return index;
		}
		return -1;
		break;
	case OVT_BALT: // bestalternate
		if ( ValidWayPoint(BestAlternate) != false ) {
			index = BestAlternate;
			if ( index >=0 ) return index;
		}
		return -1;
		break;
	case OVT_HOME: // home waypoint
		if (ValidWayPoint(HomeWaypoint)) {
			index = HomeWaypoint;
			if ( index >=0 ) return index;
		}
		return -1;
		break;

	case OVT_THER:
		index=RESWP_LASTTHERMAL;
		if (ValidResWayPoint(index)) return index;
		return -1;
		break;

	case OVT_MATE:
		index=RESWP_TEAMMATE;
		if (ValidResWayPoint(index)) return index;
		return -1;
		break;

	case OVT_FLARM:
		index=RESWP_FLARMTARGET;
		if (ValidResWayPoint(index)) return index;
		return -1;
		break;

	// 4: home, 5: traffic, 6: mountain pass, last thermal, etc.
	default:
		return -1;
		break;
  }
}
Example #28
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);
}
Example #29
0
// handle custom keys. Input: key pressed (center, left etc.)
// Returns true if handled successfully, false if not
//
// Passthrough mode for keys>=1000 (custom menu keys)
//
bool CustomKeyHandler(const int key) {

  int ckeymode;
  static bool doinit=true;
  static int oldModeIndex;

  if (doinit) {
	oldModeIndex=LKMODE_INFOMODE;;
	doinit=false;
  }

  if (key>=1000) {
	ckeymode=key-1000;
	LKASSERT((ckeymode>=0 && ckeymode<ckTOP));
	goto passthrough;
  }

  switch(key) {
	case CKI_BOTTOMCENTER:
		ckeymode=CustomKeyModeCenter;
		break;
	case CKI_BOTTOMLEFT:	
		ckeymode=CustomKeyModeLeft;
		break;
	case CKI_BOTTOMRIGHT:	
		ckeymode=CustomKeyModeRight;
		break;
	case CKI_BOTTOMICON:	
		ckeymode=CustomKeyModeAircraftIcon;
		break;
	case CKI_TOPLEFT:
		ckeymode=CustomKeyModeLeftUpCorner;
		break;
	case CKI_TOPRIGHT:
		ckeymode=CustomKeyModeRightUpCorner;
		break;
	case CKI_CENTERSCREEN:
		ckeymode=CustomKeyModeCenterScreen;
		break;
	default:
		DoStatusMessage(_T("ERR-725 UNKNOWN CUSTOMKEY"));
		return false;
		break;
  }

passthrough:

  switch(ckeymode) {
	case ckDisabled:
		break;
	case ckZoomIn:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		MapWindow::zoom.EventScaleZoom(1);
		return true;
		break;
	case ckZoomInMore:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		MapWindow::zoom.EventScaleZoom(2);
		return true;
		break;
	case ckZoomOut:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		MapWindow::zoom.EventScaleZoom(-1);
		return true;
		break;
	case ckZoomOutMore:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		MapWindow::zoom.EventScaleZoom(-2);
		return true;
		break;
	case ckMenu:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		ShowMenu();
		return true;
	case ckBackMode:
		PreviousModeIndex();
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckToggleMap: //TODO
		if (ModeIndex==LKMODE_MAP)
			SetModeIndex(oldModeIndex);
		else {
			oldModeIndex=ModeIndex;
			SetModeIndex(LKMODE_MAP);
		}
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;

	case ckTrueWind:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::setMode(_T("TrueWind"));
		return true;

	case ckTeamCode:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventSetup(_T("Teamcode"));
		return true;

	case ckToggleOverlays:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		ToggleMultimapOverlays();
		return true;

	case ckToggleMapLandable:
		if (ModeIndex==LKMODE_MAP)
			SetModeIndex(LKMODE_WP);
		else
			SetModeIndex(LKMODE_MAP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckLandables:
		SetModeIndex(LKMODE_WP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckToggleMapCommons:
		if (ModeIndex==LKMODE_MAP)
			SetModeIndex(LKMODE_NAV);
		else
			SetModeIndex(LKMODE_MAP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckCommons:
		SetModeIndex(LKMODE_NAV);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckToggleMapTraffic:
		if (ModeIndex==LKMODE_MAP)
			SetModeIndex(LKMODE_TRF);
		else
			SetModeIndex(LKMODE_MAP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckTraffic:
		SetModeIndex(LKMODE_TRF);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckInvertColors:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventInvertColor(NULL);
		return true;
	case ckTimeGates:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventTimeGates(NULL);
		return true;
	case ckMarkLocation:
		InputEvents::eventMarkLocation(_T(""));
		return true;
	case ckAutoZoom:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventZoom(_T("auto toggle"));
		InputEvents::eventZoom(_T("auto show"));
		return true;
	case ckActiveMap:
		// NO MORE USED BUT KEPT FOR OPTIMIZING COMPILER
		return true;
	case ckBooster:
		DoStatusMessage(_T("FEEL THE THERMAL"));
		if (EnableSoundModes) LKSound(_T("LK_BOOSTER.WAV"));
		return true;
	case ckGoHome:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		if (ValidWayPoint(HomeWaypoint)) {
			if ( (ValidTaskPoint(ActiveWayPoint)) && (Task[ActiveWayPoint].Index == HomeWaypoint )) {
	// LKTOKEN  _@M82_ = "Already going home" 
				DoStatusMessage(gettext(TEXT("_@M82_")));
			} else {
				GotoWaypoint(HomeWaypoint);
			}
		} else
	// LKTOKEN  _@M465_ = "No Home to go!" 
			DoStatusMessage(gettext(TEXT("_@M465_")));
		return true;
	case ckPanorama:
		if (PGZoomTrigger==false)
			PGZoomTrigger=true;
		else
			LastZoomTrigger=0;
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		return true;

	case ckMultitargetRotate:
		RotateOvertarget();
		return true;

	case ckMultitargetMenu:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::setMode(_T("MTarget"));
		return true;
	case ckBaroToggle:
		ToggleBaroAltitude();
		return true;
	case ckBasicSetup:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventSetup(_T("Basic"));
		return true;
	case ckSimMenu:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::setMode(_T("SIMMENU"));
		return true;
	case ckToggleMapAirspace:
		if (ModeIndex==LKMODE_MAP)
			SetModeType(LKMODE_WP,WP_AIRSPACES);
		else
			SetModeIndex(LKMODE_MAP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckAirspaceAnalysis:
		SetModeType(LKMODE_MAP,MP_MAPASP);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckOptimizeRoute:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		PGOptimizeRoute=!PGOptimizeRoute;
		if (ISPARAGLIDER && PGOptimizeRoute) {
			AATEnabled = true;
            ClearOptimizedTargetPos();
		}
		return true;
	case ckLockScreen:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventService(_T("LOCKMODE"));
		return true;
	case ckWhereAmI:
		// no sound here, chime is played by service event
		InputEvents::eventService(_T("ORACLE"));
		return true;
	case ckUseTotalEnergy:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventService(_T("TOTALEN"));
		return true;
	case ckNotepad:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventChecklist(_T(""));
		return true;
	case ckTerrainColors:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventService(_T("TERRCOL"));
		return true;
	case ckNearestAirspace:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventNearestAirspaceDetails(NULL);
		return true;
	case ckOlcAnalysis:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventSetup(_T("OlcAnalysis"));
		return true;
	case ckTerrainColorsBack:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventService(_T("TERRCOLBACK"));
		return true;
	case ckForceFreeFlightRestart:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		if (!CALCULATED_INFO.Flying) {
			DoStatusMessage(MsgToken(922)); // NOT FLYING
		} else {
			if (MessageBoxX(hWndMapWindow, MsgToken(1754), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) {
				LKSW_ForceFreeFlightRestart=true;
			}
		}
		return true;
	case ckCustomMenu1:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		extern void dlgCustomMenuShowModal(void);
		InputEvents::eventMode(_T("MYMODE"));
		return true;
	case ckTaskCalc:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventCalculator(NULL);
		return true;
	case ckTaskTarget:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventSetup(_T("Target"));
		return true;
	case ckArmAdvance:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventArmAdvance(_T("toggle"));
		InputEvents::eventArmAdvance(_T("show"));
		return true;

	case ckMessageRepeat:
		InputEvents::eventRepeatStatusMessage(NULL);
                return true;
		
	case ckWaypointLookup:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventWaypointDetails(_T("select"));
		return true;

	case ckPan:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		InputEvents::eventPan(_T("toggle"));
		return true;

	case ckWindRose:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		UseWindRose=!UseWindRose;
		return true;

	case ckFlarmRadar:
		SetModeType(LKMODE_MAP,MP_RADAR);
		MapWindow::RefreshMap();
		SoundModeIndex();
		return true;
	case ckDeviceA:
		if(devA() && devA()->Config) {
			devA()->Config(devA());
		}
		return true;
	case ckDeviceB:
		if(devB() && devB()->Config) {
			devB()->Config(devB());
		}
		return true;
	case ckResetOdometer:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		if (MessageBoxX(hWndMapWindow, MsgToken(2229), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) {
			LKSW_ResetOdometer=true;
		}
		return true;
	case ckForceLanding:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		if ( !CALCULATED_INFO.Flying ) {
			DoStatusMessage(MsgToken(922)); // NOT FLYING
		} else {
			if ( (GPS_INFO.Speed > TakeOffSpeedThreshold) && (!GPS_INFO.NAVWarning) ) {
				DoStatusMessage(MsgToken(1799)); // STOP MOVING!
			} else {
				if (MessageBoxX(hWndMapWindow, MsgToken(2230), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) {
					LKSW_ForceLanding=true;
				}
			}
		}
		return true;
	case ckResetTripComputer:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
		if (MessageBoxX(hWndMapWindow, MsgToken(2236), _T(""), MB_YESNO|MB_ICONQUESTION) == IDYES) {
			LKSW_ResetTripComputer=true;
		}
		return true;
	case ckSonarToggle:
		SonarWarning = !SonarWarning;
		TCHAR sonarmsg[60];
		_stprintf(sonarmsg,_T("%s "),MsgToken(1293)); // SONAR
		if (SonarWarning)
			_tcscat(sonarmsg,MsgToken(1643)); // ENABLED
		else
			_tcscat(sonarmsg,MsgToken(1600)); // DISABLED
		DoStatusMessage(sonarmsg,NULL,false);
		if (EnableSoundModes) {
			if (SonarWarning)
				LKSound(TEXT("LK_TONEUP.WAV"));
			else
				LKSound(TEXT("LK_TONEDOWN.WAV"));
		}
		return true;
	case ckResetView:
		ModeType[LKMODE_MAP]    =       MP_MOVING;
		ModeType[LKMODE_INFOMODE]=      IM_CRUISE;
		ModeType[LKMODE_WP]     =       WP_AIRPORTS;
		ModeType[LKMODE_NAV]    =       NV_COMMONS;
		ModeType[LKMODE_TRF]    =       TF_LIST;

		SetModeType(LKMODE_MAP,MP_MOVING);
		MapWindow::RefreshMap();
		SoundModeIndex();

		return true;

	case  ckMapOrient:
		#ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif

		TCHAR MapOrientMsg[60];

	    if  (MapSpaceMode==MSM_MAP)
	    {
	      DisplayOrientation++;
	      if(DisplayOrientation > NORTHSMART)
	    	DisplayOrientation = 0;
	      MapWindow::SetAutoOrientation(true); // 101008 reset it
	      switch(DisplayOrientation)
	      {
            case TRACKUP     : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M737_"))) ; break;  // _@M737_ "Track up"
            case NORTHUP     : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M483_"))) ; break;  // _@M483_ "North up"
            case NORTHCIRCLE : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M482_"))) ; break;  // _@M482_ "North circling"
            case TRACKCIRCLE : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M682_"))) ; break;  // _@M682_ "Target circling"  _@M485_ "NorthUp above "
            case NORTHTRACK  : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M484_"))) ; break;  // _@M484_ "North/track"
            case NORTHSMART  : _stprintf(MapOrientMsg,_T("%s"),gettext(TEXT("_@M481_"))) ; break;  // _@M481_ "North Smart"
	      }
	      DoStatusMessage(MapOrientMsg,NULL,false);
	    }
	    else
	    {
		  SetMMNorthUp(GetSideviewPage(), (GetMMNorthUp(GetSideviewPage())+1)%2);
	    }

		return true;
    case ckResetComm:
        #ifndef DISABLEAUDIO
		if (EnableSoundModes) PlayResource(TEXT("IDR_WAV_CLICK"));
		#endif
        InputEvents::eventRestartCommPorts(NULL);
        return true;
	default:
		DoStatusMessage(_T("ERR-726 INVALID CUSTOMKEY"));
		StartupStore(_T("... ERR-726 INVALID CUSTOMKEY=%d\n"),ckeymode);
		break;
  }

  return false;

}
Example #30
0
void MapWindow::DrawTask(HDC hdc, RECT rc, const POINT &Orig_Aircraft) {
    int i;
    double tmp;

    COLORREF whitecolor = RGB_WHITE;
    COLORREF origcolor = SetTextColor(hDCTemp, whitecolor);
    HPEN oldpen = 0;
    HBRUSH oldbrush = 0;

    static short size_tasklines=0;

    if (DoInit[MDI_DRAWTASK]) {
switch (ScreenSize) {
case ss480x272:
case ss272x480:
case ss320x240:
case ss240x320:
size_tasklines=NIBLSCALE(4);
break;
default:
size_tasklines=NIBLSCALE(3);
break;
}
DoInit[MDI_DRAWTASK]=false;
    }

    if (!WayPointList) return;

    oldpen = (HPEN) SelectObject(hdc, hpStartFinishThick);
    oldbrush = (HBRUSH) SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));

    LockTaskData(); // protect from external task changes

    for (i = 1; ValidTaskPoint(i); i++) {
        if (!ValidTaskPoint(i + 1)) { // final waypoint
            if (ActiveWayPoint > 1 || !ValidTaskPoint(2)) {
                // only draw finish line when past the first
                // waypoint. FIXED 110307: or if task is with only 2 tps
                DrawStartEndSector(hdc, rc, Task[i].Start, Task[i].End, Task[i].Index, FinishLine, FinishRadius);
            }
        } else { // normal sector
            if (AATEnabled != TRUE) {
                //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc);
                //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc);
         // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc);
         // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc);
            }

            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(i, &Type, &Radius);
            switch (Type) {
                case CIRCLE:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    Circle(hdc,
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y,
                            (int) tmp, rc, false, false);
                    break;
                case SECTOR:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    Segment(hdc,
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y, (int) tmp, rc,
                            Task[i].AATStartRadial - DisplayAngle,
                            Task[i].AATFinishRadial - DisplayAngle);
                    break;
                case DAe:
                    if (!AATEnabled) { // this Type exist only if not AAT task
                        // JMW added german rules
                        tmp = 500 * zoom.ResScaleOverDistanceModify();
                        Circle(hdc,
                                WayPointList[Task[i].Index].Screen.x,
                                WayPointList[Task[i].Index].Screen.y,
                                (int) tmp, rc, false, false);

                        tmp = 10e3 * zoom.ResScaleOverDistanceModify();

                        Segment(hdc,
                                WayPointList[Task[i].Index].Screen.x,
                                WayPointList[Task[i].Index].Screen.y, (int) tmp, rc,
                                Task[i].AATStartRadial - DisplayAngle,
                                Task[i].AATFinishRadial - DisplayAngle);
                    }
                    break;
                case LINE:
                    if (!AATEnabled) { // this Type exist only if not AAT task
                    	if(ISGAAIRCRAFT) {
                    		POINT start,end;
                    		double rotation=AngleLimit360(Task[i].Bisector-DisplayAngle);
                    		int length=14*ScreenScale; //Make intermediate WP lines always of the same size independent by zoom level
                    		start.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation));
                    		start.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation));
                    		rotation=Reciprocal(rotation);
                    		end.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation));
                    		end.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation));
                    		_DrawLine(hdc, PS_SOLID, NIBLSCALE(3), start, end, taskcolor, rc);
                    	} else _DrawLine(hdc, PS_SOLID, NIBLSCALE(3), Task[i].Start, Task[i].End, taskcolor, rc);
                    }
                    break;
                case CONE:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    int center_x = WayPointList[Task[i].Index].Screen.x;
                    int center_y = WayPointList[Task[i].Index].Screen.y;
                    Circle(hdc, center_x, center_y, (int) tmp, rc, false, false);
                    HPEN prevPen = (HPEN)::SelectObject(hdc, hpTerrainLine);
                    for( int j = 1; j < 5 && tmp > 0; ++j) {
                        Circle(hdc, center_x, center_y, tmp -= NIBLSCALE(5), rc, true, true);
                    }
                    ::SelectObject(hdc, prevPen);
                    break;
            }

            if (AATEnabled && !DoOptimizeRoute()) {
                // ELSE HERE IS *** AAT ***
                // JMW added iso lines
                if ((i == ActiveWayPoint) || (mode.Is(Mode::MODE_TARGET_PAN) && (i == TargetPanIndex))) {
                    // JMW 20080616 flash arc line if very close to target
                    static bool flip = false;

                    if (DerivedDrawInfo.WaypointDistance < AATCloseDistance()*2.0) {
                        flip = !flip;
                    } else {
                        flip = true;
                    }
                    if (flip) {
                        for (int j = 0; j < MAXISOLINES - 1; j++) {
                            if (TaskStats[i].IsoLine_valid[j]
                                    && TaskStats[i].IsoLine_valid[j + 1]) {
                                _DrawLine(hdc, PS_SOLID, NIBLSCALE(2),
                                        TaskStats[i].IsoLine_Screen[j],
                                        TaskStats[i].IsoLine_Screen[j + 1],
                                        RGB(0, 0, 255), rc);
                            }
                        }
                    }
                }
            }
        }
    }

    if ((ActiveWayPoint < 2) && ValidTaskPoint(0) && ValidTaskPoint(1)) {
        DrawStartEndSector(hdc, rc, Task[0].Start, Task[0].End, Task[0].Index, StartLine, StartRadius);
        if (EnableMultipleStartPoints) {
            for (i = 0; i < MAXSTARTPOINTS; i++) {
                if (StartPoints[i].Active && ValidWayPoint(StartPoints[i].Index)) {
                    DrawStartEndSector(hdc, rc, StartPoints[i].Start, StartPoints[i].End,
                            StartPoints[i].Index, StartLine, StartRadius);
                }
            }
        }
    }
    
    for (i = 0; ValidTaskPoint(i + 1); i++) {
        int imin = min(Task[i].Index, Task[i + 1].Index);
        int imax = max(Task[i].Index, Task[i + 1].Index);
        // JMW AAT!
        double bearing = Task[i].OutBound;
        POINT sct1, sct2;
        if (AATEnabled) {
            LatLon2Screen(Task[i].AATTargetLon,
                    Task[i].AATTargetLat,
                    sct1);
            LatLon2Screen(Task[i + 1].AATTargetLon,
                    Task[i + 1].AATTargetLat,
                    sct2);
            DistanceBearing(Task[i].AATTargetLat,
                    Task[i].AATTargetLon,
                    Task[i + 1].AATTargetLat,
                    Task[i + 1].AATTargetLon,
                    NULL, &bearing);

            // draw nominal track line
            DrawDashLine(hdc, NIBLSCALE(1), // 091217
                    WayPointList[imin].Screen,
                    WayPointList[imax].Screen,
                    taskcolor, rc);
        } else {
            sct1 = WayPointList[imin].Screen;
            sct2 = WayPointList[imax].Screen;
        }

        if ((i >= ActiveWayPoint && DoOptimizeRoute()) || !DoOptimizeRoute()) {
            POINT ClipPt1 = sct1, ClipPt2 = sct2;
            if(LKGeom::ClipLine((POINT) {rc.left, rc.top}, (POINT) {rc.right, rc.bottom}, ClipPt1, ClipPt2)) {
                DrawMulticolorDashLine(hdc, size_tasklines,
                        sct1,
                        sct2,
                        taskcolor, RGB_BLACK,rc);
                
                // draw small arrow along task direction
                POINT p_p;
                POINT Arrow[2] = {
                    {6, 6},
                    {-6, 6}
                };
                ScreenClosestPoint(sct1, sct2,
                        Orig_Aircraft, &p_p, NIBLSCALE(25));
                threadsafePolygonRotateShift(Arrow, 2, p_p.x, p_p.y, bearing - DisplayAngle);

                _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[0], p_p, taskcolor, rc);
                _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[1], p_p, taskcolor, rc);
            }
        }
    }
    
    // Draw DashLine From current position to Active TurnPoint center
    if(ValidTaskPoint(ActiveWayPoint)) {
        POINT ptStart;
        LatLon2Screen(DrawInfo.Longitude, DrawInfo.Latitude, ptStart);
        DrawDashLine(hdc, NIBLSCALE(1),
                    ptStart,
                    WayPointList[Task[ActiveWayPoint].Index].Screen,
                    taskcolor, rc);

    }

    {
        UnlockTaskData();
    }

    // restore original color
    SetTextColor(hDCTemp, origcolor);
    SelectObject(hdc, oldpen);
    SelectObject(hdc, oldbrush);
}