void AATDistance::ShiftTargetFromInFront(double longitude, double latitude, int taskwaypoint) { double course_bearing; // this point is in sector and is improved // JMW, now moves target to in line with previous target whenever // you are in AAT sector and improving on the target distance //JMWAAT Task[taskwaypoint].AATTargetOffsetRadial = -1.0; if (Task[taskwaypoint].AATTargetLocked) { // have improved on the locked value, so unlock it in case user // wants to move it. Task[taskwaypoint].AATTargetOffsetRadius = -1.0; Task[taskwaypoint].AATTargetOffsetRadial = 0; Task[taskwaypoint].AATTargetLocked = false; } DistanceBearing(Task[taskwaypoint-1].AATTargetLat, Task[taskwaypoint-1].AATTargetLon, latitude, longitude, NULL, &course_bearing); course_bearing = AngleLimit360(course_bearing+ Task[taskwaypoint].AATTargetOffsetRadial); FindLatitudeLongitude(latitude, longitude, course_bearing, AATCloseDistance(), &Task[taskwaypoint].AATTargetLat, &Task[taskwaypoint].AATTargetLon); // JMW, distance here was 100m, now changed to speed * 2 UpdateTargetAltitude(Task[taskwaypoint]); TargetModified = true; CalculateAATIsoLines(); }
void TaskStatistics(NMEA_INFO *Basic, DERIVED_INFO *Calculated, const double this_maccready) { if (!ValidTaskPoint(ActiveWayPoint) || ((ActiveWayPoint>0) && !ValidTaskPoint(ActiveWayPoint-1))) { Calculated->LegSpeed = 0; Calculated->LegDistanceToGo = 0; Calculated->LegDistanceCovered = 0; Calculated->LegTimeToGo = 0; if (!AATEnabled) { Calculated->AATTimeToGo = 0; } // Calculated->TaskSpeed = 0; Calculated->TaskDistanceToGo = 0; Calculated->TaskDistanceCovered = 0; Calculated->TaskTimeToGo = 0; Calculated->LKTaskETE = 0; Calculated->TaskTimeToGoTurningNow = -1; Calculated->TaskAltitudeRequired = 0; Calculated->TaskAltitudeDifference = 0; Calculated->TaskAltitudeDifference0 = 0; Calculated->TaskAltitudeArrival = 0; Calculated->TerrainWarningLatitude = 0.0; Calculated->TerrainWarningLongitude = 0.0; Calculated->GRFinish = INVALID_GR; Calculated->FinalGlide = false; CheckGlideThroughTerrain(Basic, Calculated); // BUGFIX 091123 // no task selected, so work things out at current heading GlidePolar::MacCreadyAltitude(this_maccready, 100.0, Basic->TrackBearing, Calculated->WindSpeed, Calculated->WindBearing, &(Calculated->BestCruiseTrack), &(Calculated->VMacCready), (Calculated->FinalGlide==true), NULL, 1.0e6, CRUISE_EFFICIENCY); return; } // LockFlightData(); LockTaskData(); // Calculate Task Distances // First calculate distances for this waypoint double LegCovered, LegToGo=0, LegXTD=0, LegCurrentCourse; double LegDistance, LegBearing=0; bool calc_turning_now; double w1lat; double w1lon; double w0lat; double w0lon; if (AATEnabled && (ActiveWayPoint>0) && (ValidTaskPoint(ActiveWayPoint))) { w1lat = Task[ActiveWayPoint].AATTargetLat; w1lon = Task[ActiveWayPoint].AATTargetLon; } else { w1lat = WayPointList[TASKINDEX].Latitude; w1lon = WayPointList[TASKINDEX].Longitude; } DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, &LegToGo, &LegBearing); if (AATEnabled && (ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1) && Calculated->IsInSector && (this_maccready>0.1) ) { calc_turning_now = true; } else { calc_turning_now = false; } if (ActiveWayPoint<1) { LegCovered = 0; LegCurrentCourse=LegBearing; if (ValidTaskPoint(ActiveWayPoint+1)) { // BUGFIX 091221 LegToGo=0; } } else { if (AATEnabled) { LKASSERT((ActiveWayPoint-1)>=0); // TODO accuracy: Get best range point to here... w0lat = Task[ActiveWayPoint-1].AATTargetLat; w0lon = Task[ActiveWayPoint-1].AATTargetLon; } else { LKASSERT((ActiveWayPoint-1)>=0); LKASSERT(ValidTaskPoint(ActiveWayPoint-1)); w0lat = WayPointList[Task[ActiveWayPoint-1].Index].Latitude; w0lon = WayPointList[Task[ActiveWayPoint-1].Index].Longitude; } DistanceBearing(w1lat, w1lon, w0lat, w0lon, &LegDistance, NULL); LegCovered = ProjectedDistance(w0lon, w0lat, w1lon, w1lat, Basic->Longitude, Basic->Latitude, &LegXTD, &LegCurrentCourse); if ((StartLine==0) && (ActiveWayPoint==1)) { // Correct speed calculations for radius // JMW TODO accuracy: legcovered replace this with more accurate version // LegDistance -= StartRadius; LegCovered = max(0.0, LegCovered-StartRadius); } } Calculated->LegDistanceToGo = LegToGo; Calculated->LegDistanceCovered = LegCovered; Calculated->LegCrossTrackError = LegXTD; Calculated->LegActualTrueCourse = LegCurrentCourse; Calculated->TaskDistanceCovered = LegCovered; if (Basic->Time > Calculated->LegStartTime) { if (flightstats.LegStartTime[ActiveWayPoint]<0) { flightstats.LegStartTime[ActiveWayPoint] = Basic->Time; } Calculated->LegSpeed = Calculated->LegDistanceCovered / (Basic->Time - Calculated->LegStartTime); } // Now add distances for start to previous waypoint if (!AATEnabled) { for(int i=0;i< ActiveWayPoint-1; i++) { if (!ValidTaskPoint(i) || !ValidTaskPoint(i+1)) continue; w1lat = WayPointList[Task[i].Index].Latitude; w1lon = WayPointList[Task[i].Index].Longitude; w0lat = WayPointList[Task[i+1].Index].Latitude; w0lon = WayPointList[Task[i+1].Index].Longitude; DistanceBearing(w1lat, w1lon, w0lat, w0lon, &LegDistance, NULL); Calculated->TaskDistanceCovered += LegDistance; } } else if (ActiveWayPoint>0) { // JMW added correction for distance covered Calculated->TaskDistanceCovered = aatdistance.DistanceCovered(Basic->Longitude, Basic->Latitude, ActiveWayPoint); } CheckTransitionFinalGlide(Basic, Calculated); // accumulators double TaskAltitudeRequired = 0; double TaskAltitudeRequired0 = 0; Calculated->TaskDistanceToGo = 0; Calculated->TaskTimeToGo = 0; Calculated->LKTaskETE = 0; Calculated->TaskTimeToGoTurningNow = 0; Calculated->TaskAltitudeArrival = 0; double LegTime0; // Calculate Final Glide To Finish int FinalWayPoint = getFinalWaypoint(); double final_height = FAIFinishHeight(Basic, Calculated, -1); double total_energy_height = Calculated->NavAltitude + Calculated->EnergyHeight; double height_above_finish = total_energy_height - final_height; if (ISPARAGLIDER) { TaskAltitudeRequired = final_height; TaskAltitudeRequired0 = final_height; } // Now add it for remaining waypoints int task_index= FinalWayPoint; double StartBestCruiseTrack = -1; while ((task_index>ActiveWayPoint) && (ValidTaskPoint(task_index))) { double this_LegTimeToGo; bool this_is_final = (task_index==FinalWayPoint) || ForceFinalGlide; this_is_final = true; // JMW CHECK FGAMT if (AATEnabled) { w1lat = Task[task_index].AATTargetLat; w1lon = Task[task_index].AATTargetLon; w0lat = Task[task_index-1].AATTargetLat; w0lon = Task[task_index-1].AATTargetLon; } else { w1lat = WayPointList[Task[task_index].Index].Latitude; w1lon = WayPointList[Task[task_index].Index].Longitude; w0lat = WayPointList[Task[task_index-1].Index].Latitude; w0lon = WayPointList[Task[task_index-1].Index].Longitude; } double NextLegDistance, NextLegBearing; DistanceBearing(w0lat, w0lon, w1lat, w1lon, &NextLegDistance, &NextLegBearing); double LegAltitude = GlidePolar:: MacCreadyAltitude(this_maccready, NextLegDistance, NextLegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, this_is_final, &this_LegTimeToGo, height_above_finish, CRUISE_EFFICIENCY); double LegAltitude0 = GlidePolar:: MacCreadyAltitude(0, NextLegDistance, NextLegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, true, &LegTime0, 1.0e6, CRUISE_EFFICIENCY ); if (LegTime0>=0.9*ERROR_TIME) { // can't make it, so assume flying at current mc LegAltitude0 = LegAltitude; } TaskAltitudeRequired += LegAltitude; TaskAltitudeRequired0 += LegAltitude0; if(ISPARAGLIDER) { // if required altitude is less than previous turpoint altitude, // use previous turn point altitude double w0Alt = FAIFinishHeight(Basic, Calculated, task_index-1); if(TaskAltitudeRequired < w0Alt) { Calculated->TaskAltitudeArrival += w0Alt - TaskAltitudeRequired; TaskAltitudeRequired = w0Alt; } if(TaskAltitudeRequired0 < w0Alt) { TaskAltitudeRequired0 = w0Alt; } } Calculated->TaskDistanceToGo += NextLegDistance; Calculated->TaskTimeToGo += this_LegTimeToGo; if (task_index==1) { StartBestCruiseTrack = NextLegBearing; } if (calc_turning_now) { if (task_index == ActiveWayPoint+1) { double NextLegDistanceTurningNow, NextLegBearingTurningNow; double this_LegTimeToGo_turningnow=0; DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, &NextLegDistanceTurningNow, &NextLegBearingTurningNow); GlidePolar:: MacCreadyAltitude(this_maccready, NextLegDistanceTurningNow, NextLegBearingTurningNow, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, this_is_final, &this_LegTimeToGo_turningnow, height_above_finish, CRUISE_EFFICIENCY); Calculated->TaskTimeToGoTurningNow += this_LegTimeToGo_turningnow; } else { Calculated->TaskTimeToGoTurningNow += this_LegTimeToGo; } } height_above_finish-= LegAltitude; task_index--; } // current waypoint, do this last! if (AATEnabled && (ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1) && Calculated->IsInSector) { if (Calculated->WaypointDistance<AATCloseDistance()*3.0) { LegBearing = AATCloseBearing(Basic, Calculated); } } #ifdef BCT_ALT_FIX // Don't calculate BCT yet. LegAltitude will be used to calculate // task altitude difference, which will then be used to calculate BCT. #endif double LegAltitude = GlidePolar::MacCreadyAltitude(this_maccready, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, #ifdef BCT_ALT_FIX 0, #else &(Calculated->BestCruiseTrack), #endif &(Calculated->VMacCready), // (Calculated->FinalGlide==1), true, // JMW CHECK FGAMT &(Calculated->LegTimeToGo), height_above_finish, CRUISE_EFFICIENCY); double LegAltitude0 = GlidePolar::MacCreadyAltitude(0, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, true, &LegTime0, 1.0e6, CRUISE_EFFICIENCY ); #ifndef BCT_ALT_FIX // fix problem of blue arrow wrong in task sector if (StartBestCruiseTrack>=0) // use it only if assigned, workaround if (Calculated->IsInSector && (ActiveWayPoint==0)) { // set best cruise track to first leg bearing when in start sector Calculated->BestCruiseTrack = StartBestCruiseTrack; } #endif // JMW TODO accuracy: Use safetymc where appropriate if (LegTime0>= 0.9*ERROR_TIME) { // can't make it, so assume flying at current mc LegAltitude0 = LegAltitude; } TaskAltitudeRequired += LegAltitude; TaskAltitudeRequired0 += LegAltitude0; Calculated->TaskDistanceToGo += LegToGo; Calculated->TaskTimeToGo += Calculated->LegTimeToGo; #ifndef BCT_ALT_FIX height_above_finish-= LegAltitude; #endif if (calc_turning_now) { Calculated->TaskTimeToGoTurningNow += Basic->Time-Calculated->TaskStartTime; } else { Calculated->TaskTimeToGoTurningNow = -1; } if (ISPARAGLIDER) { Calculated->TaskAltitudeRequired = TaskAltitudeRequired; } else { Calculated->TaskAltitudeRequired = TaskAltitudeRequired + final_height; TaskAltitudeRequired0 += final_height; } Calculated->TaskAltitudeDifference = total_energy_height - Calculated->TaskAltitudeRequired; Calculated->TaskAltitudeDifference0 = total_energy_height - TaskAltitudeRequired0; Calculated->NextAltitudeDifference0 = total_energy_height - Calculated->NextAltitudeRequired0; Calculated->TaskAltitudeArrival += Calculated->TaskAltitudeDifference; Calculated->GRFinish= CalculateGlideRatio(Calculated->TaskDistanceToGo, Calculated->NavAltitude - final_height); if (Calculated->TaskSpeedAchieved >0) Calculated->LKTaskETE = Calculated->TaskDistanceToGo/Calculated->TaskSpeedAchieved; else Calculated->LKTaskETE=0; #ifdef BCT_ALT_FIX // This MCA call's only purpose is to update BestCruiseTrack (BCT). // It must occur after TaskAltitudeDifference (TAD) is updated, // since BCT depends on TAD. GlidePolar::MacCreadyAltitude(this_maccready, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, &(Calculated->BestCruiseTrack), 0, true, 0, height_above_finish, CRUISE_EFFICIENCY, Calculated->TaskAltitudeDifference); // fix problem of blue arrow wrong in task sector if (StartBestCruiseTrack>=0) // use it only if assigned, workaround if (Calculated->IsInSector && (ActiveWayPoint==0)) { // set best cruise track to first leg bearing when in start sector Calculated->BestCruiseTrack = StartBestCruiseTrack; } height_above_finish-= LegAltitude; #endif CheckGlideThroughTerrain(Basic, Calculated); CheckForceFinalGlide(Basic, Calculated); UnlockTaskData(); }
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); }
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 = SectorType; double Radius = SectorRadius; if (AATEnabled) { Type = Task[i].AATType; Radius = Task[i].AATCircleRadius; } 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 2: 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; } 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++) { bool is_first = (Task[i].Index < Task[i + 1].Index); 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[Task[i].Index].Screen; sct2 = WayPointList[Task[i + 1].Index].Screen; } if ((i >= ActiveWayPoint && DoOptimizeRoute()) || !DoOptimizeRoute()) { if (is_first) { DrawMulticolorDashLine(hdc, size_tasklines, sct1, sct2, taskcolor, RGB_BLACK,rc); } else { DrawMulticolorDashLine(hdc, size_tasklines, sct2, sct1, 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)); PolygonRotateShift(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); } } { UnlockTaskData(); } // restore original color SetTextColor(hDCTemp, origcolor); SelectObject(hdc, oldpen); SelectObject(hdc, oldbrush); }
void DistanceToNext(NMEA_INFO *Basic, DERIVED_INFO *Calculated) { // LockFlightData(); LockTaskData(); if(ValidTaskPoint(ActiveWayPoint)) { double w1lat, w1lon; double w0lat, w0lon; if(DoOptimizeRoute()) { w0lat = Task[ActiveWayPoint].AATTargetLat; w0lon = Task[ActiveWayPoint].AATTargetLon; } else { w0lat = WayPointList[TASKINDEX].Latitude; w0lon = WayPointList[TASKINDEX].Longitude; } DistanceBearing(Basic->Latitude, Basic->Longitude, w0lat, w0lon, &Calculated->WaypointDistance, &Calculated->WaypointBearing); Calculated->ZoomDistance = Calculated->WaypointDistance; if (AATEnabled && (ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1)) { w1lat = Task[ActiveWayPoint].AATTargetLat; w1lon = Task[ActiveWayPoint].AATTargetLon; DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, &Calculated->WaypointDistance, &Calculated->WaypointBearing); if (Calculated->WaypointDistance>AATCloseDistance()*3.0) { Calculated->ZoomDistance = max(Calculated->WaypointDistance, Calculated->ZoomDistance); } else { Calculated->WaypointBearing = AATCloseBearing(Basic, Calculated); } } else if ((ActiveWayPoint==0) && (ValidTaskPoint(ActiveWayPoint+1)) && (Calculated->IsInSector) ) { // JMW set waypoint bearing to start direction if in start sector if (AATEnabled) { w1lat = Task[ActiveWayPoint+1].AATTargetLat; w1lon = Task[ActiveWayPoint+1].AATTargetLon; } else { w1lat = WayPointList[Task[ActiveWayPoint+1].Index].Latitude; w1lon = WayPointList[Task[ActiveWayPoint+1].Index].Longitude; } DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, NULL, &Calculated->WaypointBearing); } } else { Calculated->ZoomDistance = 0; Calculated->WaypointDistance = 0; Calculated->WaypointBearing = 0; } UnlockTaskData(); // UnlockFlightData(); }
void AATDistance::ShiftTargetFromBehind(double longitude, double latitude, int taskwaypoint) { // JMWAAT if being externally updated e.g. from task dialog, don't move it if (TargetDialogOpen) return; if (taskwaypoint==0) return; // best is decreasing or first entry in sector, so project // target in direction of improvement or first entry into sector double course_bearing; double course_bearing_orig; double d_total_orig; double d_total_this; d_total_this = DoubleLegDistance(taskwaypoint, longitude, latitude); d_total_orig = DoubleLegDistance(taskwaypoint, Task[taskwaypoint].AATTargetLon, Task[taskwaypoint].AATTargetLat); if (d_total_this>d_total_orig-2.0*AATCloseDistance()) { // this is better than the previous best! (or very close) ShiftTargetFromInFront(longitude, latitude, taskwaypoint); return; } // JMWAAT if locked, don't move it if (Task[taskwaypoint].AATTargetLocked) { // 20080615 JMW don't do this; locked stays locked // Task[taskwaypoint].AATTargetLocked = false; // JMWAAT JB return; } /* // check to see if deviation is big enough to adjust target along track DistanceBearing(Task[taskwaypoint-1].AATTargetLat, Task[taskwaypoint-1].AATTargetLon, latitude, longitude, NULL, &course_bearing); DistanceBearing(Task[taskwaypoint-1].AATTargetLat, Task[taskwaypoint-1].AATTargetLon, Task[taskwaypoint].AATTargetLat, Task[taskwaypoint].AATTargetLon, NULL, &course_bearing_orig); if (fabs(AngleLimit180(course_bearing-course_bearing_orig))<5.0) { // don't update it if course deviation is less than 5 degrees, // otherwise we end up wasting a lot of CPU in recalculating, and also // the target ends up drifting. return; } course_bearing = AngleLimit360(course_bearing+ Task[taskwaypoint].AATTargetOffsetRadial); //JMWAAT Task[taskwaypoint].AATTargetOffsetRadial = course_bearing; */ DistanceBearing(Task[taskwaypoint-1].AATTargetLat, Task[taskwaypoint-1].AATTargetLon, latitude, longitude, NULL, &course_bearing); course_bearing = AngleLimit360(course_bearing+ Task[taskwaypoint].AATTargetOffsetRadial); DistanceBearing(latitude, longitude, Task[taskwaypoint].AATTargetLat, Task[taskwaypoint].AATTargetLon, NULL, &course_bearing_orig); if (fabs(AngleLimit180(course_bearing-course_bearing_orig))<5.0) { // don't update it if course deviation is less than 5 degrees, // otherwise we end up wasting a lot of CPU in recalculating, and also // the target ends up drifting. return; } double max_distance = FindInsideAATSectorDistance(latitude, longitude, taskwaypoint, course_bearing, 0); // total distance of legs from previous through this to next target double delta = max_distance/2; // move target in line with previous target along track // at an offset to improve on max distance double t_distance_lower = 0; double t_distance = delta*2; int steps = 0; do { // find target position along projected line but // make sure it is in sector, and set at a distance // to preserve total task distance // we are aiming to make d_total_this = d_total_orig double t_lat, t_lon; FindLatitudeLongitude(latitude, longitude, course_bearing, t_distance, &t_lat, &t_lon); if (InAATTurnSector(t_lon, t_lat, taskwaypoint, 0)) { d_total_this = DoubleLegDistance(taskwaypoint, t_lon, t_lat); if (d_total_orig - d_total_this>0.0) { t_distance_lower = t_distance; // ok, can go further t_distance += delta; } else { t_distance -= delta; } } else { t_distance -= delta; } delta /= 2.0; } while ((delta>5.0) && (steps++<20)); // now scan to edge of sector to find approximate range % if (t_distance_lower>5.0) { FindLatitudeLongitude(latitude, longitude, course_bearing, t_distance_lower, &Task[taskwaypoint].AATTargetLat, &Task[taskwaypoint].AATTargetLon); UpdateTargetAltitude(Task[taskwaypoint]); Task[taskwaypoint].AATTargetOffsetRadius = FindInsideAATSectorRange(latitude, longitude, taskwaypoint, course_bearing, t_distance_lower); TargetModified = true; CalculateAATIsoLines(); } // if ((!t_in_sector) && (d_diff_total>1.0)) { // JMW TODO enhancement: this is too short now so need to lengthen the // next waypoint if possible // (re discussion with paul mander) // } }