bool InTurnSector(NMEA_INFO *Basic, DERIVED_INFO *Calculated, const int the_turnpoint) { if(!ValidTaskPoint(the_turnpoint)) return false; switch(SectorType) { case CIRCLE: if(Calculated->WaypointDistance < SectorRadius) return true; break; case SECTOR: case DAe: { if(SectorType==DAe) { // JMW added german rules if (Calculated->WaypointDistance<500) return true; } double AircraftBearing; LockTaskData(); DistanceBearing(WayPointList[Task[the_turnpoint].Index].Latitude, WayPointList[Task[the_turnpoint].Index].Longitude, Basic->Latitude , Basic->Longitude, NULL, &AircraftBearing); AircraftBearing = AircraftBearing - Task[the_turnpoint].Bisector; UnlockTaskData(); while(AircraftBearing<-180) AircraftBearing+= 360; while(AircraftBearing>180) AircraftBearing-= 360; if(AircraftBearing>=-45 && AircraftBearing<=45) { if(SectorType==SECTOR) { if(Calculated->WaypointDistance < SectorRadius) return true; } else { //It's a DAe if(Calculated->WaypointDistance < 10000) return true; // JMW added german rules } } } break; case LINE: { //First check if we simply passed the WayPoint LockTaskData(); if(Calculated->LegDistanceToGo<Task[the_turnpoint].Leg && Calculated->LegDistanceCovered>=Task[the_turnpoint].Leg) { UnlockTaskData(); return true; } //Then check if we passed the bisector bool bisectorOverpassed; if(AngleLimit360(Task[the_turnpoint].InBound-Task[the_turnpoint].Bisector) < 180) bisectorOverpassed = AngleInRange(Reciprocal(Task[the_turnpoint].Bisector),Task[the_turnpoint].Bisector,Calculated->WaypointBearing,true); else bisectorOverpassed = AngleInRange(Task[the_turnpoint].Bisector,Reciprocal(Task[the_turnpoint].Bisector),Calculated->WaypointBearing,true); UnlockTaskData(); if(bisectorOverpassed) return true; } break; default: //Unknown sector type break; } return false; }
bool InAATTurnSector(const double longitude, const double latitude, const int the_turnpoint) { double AircraftBearing; bool retval = false; if (!ValidTaskPoint(the_turnpoint)) { return false; } double distance; LockTaskData(); DistanceBearing(WayPointList[Task[the_turnpoint].Index].Latitude, WayPointList[Task[the_turnpoint].Index].Longitude, latitude, longitude, &distance, &AircraftBearing); if(Task[the_turnpoint].AATType == CIRCLE) { if(distance < Task[the_turnpoint].AATCircleRadius) { retval = true; } } else if(distance < Task[the_turnpoint].AATSectorRadius) { if (AngleInRange(Task[the_turnpoint].AATStartRadial, Task[the_turnpoint].AATFinishRadial, AngleLimit360(AircraftBearing), true)) { retval = true; } } UnlockTaskData(); return retval; }
// Used by dlgTarget only // A note about this function. We are changing map drawing parameters here, but we paint from the winmain thread. // We are NOT using this from drawthread! the dialog target pan is sort of an hack, and not a good example. // Do not consider emulating the target dialog, because it should be moved to draw thread somehow. void MapWindow::SetTargetPan(bool do_pan, int target_point, DWORD dlgSize /* = 0 */) { static double old_latitude; static double old_longitude; if(dlgSize) targetPanSize = dlgSize; if (!mode.Is(Mode::MODE_TARGET_PAN) || (TargetPanIndex != target_point)) { targetMoved = false; } TargetPanIndex = target_point; if (do_pan && !mode.Is(Mode::MODE_TARGET_PAN)) { old_latitude = PanLatitude; old_longitude = PanLongitude; mode.Special(do_pan ? Mode::MODE_SPECIAL_TARGET_PAN : Mode::MODE_SPECIAL_PAN, true); zoom.SwitchMode(); } if (do_pan) { LockTaskData(); if (ValidTaskPoint(target_point)) { PanLongitude = WayPointList[Task[target_point].Index].Longitude; PanLatitude = WayPointList[Task[target_point].Index].Latitude; if (target_point==0) { TargetZoomDistance = max(2e3, (double)StartRadius*2); } else if (!ValidTaskPoint(target_point+1)) { TargetZoomDistance = max(2e3, (double)FinishRadius*2); } else if (AATEnabled) { if (Task[target_point].AATType == SECTOR) { const double start = Task[target_point].AATStartRadial; const double finish = Task[target_point].AATFinishRadial; const double xs = fastsine(start); const double ys = fastcosine(start); const double xf = fastsine(finish); const double yf = fastcosine(finish); // calculate rectangle area taken by the sector const double top = AngleInRange(start, finish, 0, true) ? 1 : max(max(ys, yf), 0.0); const double right = AngleInRange(start, finish, 90, true) ? 1 : max(max(xs, xf), 0.0); const double bottom = AngleInRange(start, finish, 180, true) ? -1 : min(min(ys, yf), 0.0); const double left = AngleInRange(start, finish, 270, true) ? -1 : min(min(xs, xf), 0.0); // get area center const double radius = Task[target_point].AATSectorRadius; const double x = (left + right) / 2; const double y = (top + bottom) / 2; double bearing, range; xXY_Brg_Rng(0, 0, x, y, &bearing, &range); // find area center geographic data FindLatitudeLongitude(WayPointList[Task[target_point].Index].Latitude, WayPointList[Task[target_point].Index].Longitude, bearing, range * radius, &PanLatitude, &PanLongitude); TargetZoomDistance = max(2e3, max(right - left, top - bottom) * radius); } else { TargetZoomDistance = max(2e3, Task[target_point].AATCircleRadius*2); } } else { TargetZoomDistance = max(2e3, (double)SectorRadius*2); } } UnlockTaskData(); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { PanLongitude = old_longitude; PanLatitude = old_latitude; mode.Special(Mode::MODE_SPECIAL_TARGET_PAN, do_pan); zoom.SwitchMode(); } mode.Special(Mode::MODE_SPECIAL_TARGET_PAN, do_pan); }
void CalculateAATTaskSectors() { int i; int awp = ActiveTaskPoint; if(AATEnabled == FALSE || DoOptimizeRoute()) return; double latitude = GPS_INFO.Latitude; double longitude = GPS_INFO.Longitude; double altitude = GPS_INFO.Altitude; LockTaskData(); Task[0].AATTargetOffsetRadius = 0.0; Task[0].AATTargetOffsetRadial = 0.0; if (Task[0].Index>=0) { Task[0].AATTargetLat = WayPointList[Task[0].Index].Latitude; Task[0].AATTargetLon = WayPointList[Task[0].Index].Longitude; } for(i=1;i<MAXTASKPOINTS;i++) { if(ValidTaskPoint(i)) { if (!ValidTaskPoint(i+1)) { // This must be the final waypoint, so it's not an AAT OZ Task[i].AATTargetLat = WayPointList[Task[i].Index].Latitude; Task[i].AATTargetLon = WayPointList[Task[i].Index].Longitude; continue; } if(Task[i].AATType == SECTOR) { FindLatitudeLongitude (WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, Task[i].AATStartRadial , Task[i].AATSectorRadius , &Task[i].AATStartLat, &Task[i].AATStartLon); FindLatitudeLongitude (WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, Task[i].AATFinishRadial , Task[i].AATSectorRadius, &Task[i].AATFinishLat, &Task[i].AATFinishLon); } // JMWAAT: if locked, don't move it if (i<awp) { // only update targets for current/later waypoints continue; } Task[i].AATTargetOffsetRadius = min(1.0, max(Task[i].AATTargetOffsetRadius,-1.0)); Task[i].AATTargetOffsetRadial = min(90.0, max(-90.0, Task[i].AATTargetOffsetRadial)); double targetbearing; double targetrange; targetbearing = AngleLimit360(Task[i].Bisector+Task[i].AATTargetOffsetRadial); if(Task[i].AATType == SECTOR) { //AATStartRadial //AATFinishRadial targetrange = ((Task[i].AATTargetOffsetRadius+1.0)/2.0); double aatbisector = HalfAngle(Task[i].AATStartRadial, Task[i].AATFinishRadial); if (fabs(AngleLimit180(aatbisector-targetbearing))>90) { // bisector is going away from sector targetbearing = Reciprocal(targetbearing); targetrange = 1.0-targetrange; } if (!AngleInRange(Task[i].AATStartRadial, Task[i].AATFinishRadial, targetbearing,true)) { // Bisector is not within AAT sector, so // choose the closest radial as the target line if (fabs(AngleLimit180(Task[i].AATStartRadial-targetbearing)) <fabs(AngleLimit180(Task[i].AATFinishRadial-targetbearing))) { targetbearing = Task[i].AATStartRadial; } else { targetbearing = Task[i].AATFinishRadial; } } targetrange*= Task[i].AATSectorRadius; } else { targetrange = Task[i].AATTargetOffsetRadius *Task[i].AATCircleRadius; } // TODO accuracy: if i=awp and in sector, range parameter needs to // go from current aircraft position to projection of target // out to the edge of the sector if (InAATTurnSector(longitude, latitude, i, altitude) && (awp==i) && !Task[i].AATTargetLocked) { // special case, currently in AAT sector/cylinder double dist; double qdist; double bearing; // find bearing from last target through current aircraft position with offset DistanceBearing(Task[i-1].AATTargetLat, Task[i-1].AATTargetLon, latitude, longitude, &qdist, &bearing); bearing = AngleLimit360(bearing+Task[i].AATTargetOffsetRadial); dist = ((Task[i].AATTargetOffsetRadius+1)/2.0)* FindInsideAATSectorDistance(latitude, longitude, i, bearing); // if (dist+qdist>aatdistance.LegDistanceAchieved(awp)) { // JMW: don't prevent target from being closer to the aircraft // than the best achieved, so can properly plan arrival time FindLatitudeLongitude (latitude, longitude, bearing, dist, &Task[i].AATTargetLat, &Task[i].AATTargetLon); UpdateTargetAltitude(Task[i]); TargetModified = true; // } } else { FindLatitudeLongitude (WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, targetbearing, targetrange, &Task[i].AATTargetLat, &Task[i].AATTargetLon); UpdateTargetAltitude(Task[i]); TargetModified = true; } } } CalculateAATIsoLines(); if (!TargetDialogOpen) { TargetModified = false; // allow target dialog to detect externally changed targets } UnlockTaskData(); }