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; }
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(); }
// 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); }
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; } }
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(); } }
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; }
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); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// 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()
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; }
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); }
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); }
// 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(); }
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); }
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); }
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); }
// 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); }
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]); } } } }
/* * 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); }
/* * 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); }
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); }
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; } }
// 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(); }
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; }
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; }
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; }
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
// 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; } }
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); }
// 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; }
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); }