Example #1
0
  void
  AppendArc(Angle start, Angle end)
  {
    // 5 or -5, depending on direction
    const auto _step = ArcStepWidth(radius);
    const Angle step = Angle::Degrees(rotation * _step);
    const fixed threshold = _step * fixed(1.5);

    if (rotation > 0) {
      while (end < start)
        end += Angle::FullCircle();
    } else if (rotation < 0) {
      while (end > start)
        end -= Angle::FullCircle();
    }

    // Add first polygon point
    points.push_back(FindLatitudeLongitude(center, start, radius));

    // Add intermediate polygon points
    while ((end - start).AbsoluteDegrees() > threshold) {
      start += step;
      points.push_back(FindLatitudeLongitude(center, start, radius));
    }

    // Add last polygon point
    points.push_back(FindLatitudeLongitude(center, end, radius));
  }
Example #2
0
static void
CalculateSector(const TCHAR *Text, TempAirspaceType &temp_area)
{
  fixed Radius;
  TCHAR *Stop;
  GeoPoint TempPoint;
  static const fixed fixed_75 = fixed(7.5);
  const Angle BearingStep = Angle::degrees(temp_area.Rotation * fixed(5));

  Radius = Units::ToSysUnit(fixed(_tcstod(&Text[2], &Stop)), unNauticalMiles);
  Angle StartBearing = Angle::degrees(fixed(_tcstod(&Stop[1], &Stop)));
  Angle EndBearing = Angle::degrees(fixed(_tcstod(&Stop[1], &Stop)));

  if (EndBearing < StartBearing)
    EndBearing += Angle::degrees(fixed_360);

  while ((EndBearing - StartBearing).magnitude_degrees() > fixed_75) {
    StartBearing = StartBearing.as_bearing();
    FindLatitudeLongitude(temp_area.Center, StartBearing, Radius, &TempPoint);
    temp_area.points.push_back(TempPoint);
    StartBearing += BearingStep;
  }

  FindLatitudeLongitude(temp_area.Center, EndBearing, Radius, &TempPoint);
  temp_area.points.push_back(TempPoint);
}
Example #3
0
void
MapWindow::DrawProjectedTrack(Canvas &canvas)
{
  if (task == NULL || !task->Valid() || !task->getSettings().AATEnabled ||
      task->getActiveIndex() ==0)
    return;

  if (Calculated().Circling || task->TaskIsTemporary()) {
    // don't display in various modes
    return;
  }

  // TODO feature: maybe have this work even if no task?
  // TODO feature: draw this also when in target pan mode

  GEOPOINT start = Basic().Location;
  GEOPOINT previous_loc = task->getTargetLocation(task->getActiveIndex() - 1);

  double distance_from_previous, bearing;
  DistanceBearing(previous_loc, start,
		  &distance_from_previous,
		  &bearing);

  if (distance_from_previous < 100.0) {
    bearing = Basic().TrackBearing;
    // too short to have valid data
  }
  POINT pt[2] = {{0,-75},{0,-400}};
  if (SettingsMap().TargetPan) {
    double screen_range = GetScreenDistanceMeters();
    double f_low = 0.4;
    double f_high = 1.5;
    screen_range = max(screen_range, Calculated().WaypointDistance);

    GEOPOINT p1, p2;
    FindLatitudeLongitude(start,
			  bearing, f_low*screen_range,
			  &p1);
    FindLatitudeLongitude(start,
			  bearing, f_high*screen_range,
			  &p2);
    LonLat2Screen(p1, pt[0]);
    LonLat2Screen(p2, pt[1]);
  } else if (fabs(bearing-Calculated().WaypointBearing)<10) {
    // too small an error to bother
    return;
  } else {
    pt[1].y = (long)(-max(MapRectBig.right-MapRectBig.left,
			  MapRectBig.bottom-MapRectBig.top)*1.2);
    PolygonRotateShift(pt, 2, Orig_Aircraft.x, Orig_Aircraft.y,
		       bearing-DisplayAngle);
  }

  Pen dash_pen(Pen::DASH, IBLSCALE(2), Color(0, 0, 0));
  canvas.select(dash_pen);
  canvas.line(pt[0], pt[1]);
}
Example #4
0
void AATDistance::ShiftTargetOutside(double longitude, double latitude,
                                    int taskwaypoint) {
  // if no improvement possible, vector to outside
  double bearing;

  if (taskwaypoint>0) {
    DistanceBearing(latitude,
                    longitude,
                    WayPointList[Task[taskwaypoint+1].Index].Latitude,
                    WayPointList[Task[taskwaypoint+1].Index].Longitude,
                    NULL, &bearing);

    FindLatitudeLongitude(latitude, longitude,
                          bearing, 100.0,
                          &Task[taskwaypoint].AATTargetLat,
                          &Task[taskwaypoint].AATTargetLon);

    UpdateTargetAltitude(Task[taskwaypoint]);
    TargetModified = true;

  }

  //JMWAAT  Task[taskwaypoint].AATTargetOffsetRadial = bearing;

  // Move previous target to location that yields longest distance,
  // plus a little so optimal path vector points to next waypoint.
}
Example #5
0
void MapWindow::CalculateScreenPositionsThermalSources() {
    for (int i=0; i<MAX_THERMAL_SOURCES; i++) {
        if (DerivedDrawInfo.ThermalSources[i].LiftRate>0) {
            double dh = DerivedDrawInfo.NavAltitude
                        -DerivedDrawInfo.ThermalSources[i].GroundHeight;
            if (dh<0) {
                DerivedDrawInfo.ThermalSources[i].Visible = false;
                continue;
            }

            double t = dh/DerivedDrawInfo.ThermalSources[i].LiftRate;
            double lat, lon;
            FindLatitudeLongitude(DerivedDrawInfo.ThermalSources[i].Latitude,
                                  DerivedDrawInfo.ThermalSources[i].Longitude,
                                  DerivedDrawInfo.WindBearing,
                                  -DerivedDrawInfo.WindSpeed*t,
                                  &lat, &lon);
            if (PointVisible(lon,lat)) {
                LatLon2Screen(lon,
                              lat,
                              DerivedDrawInfo.ThermalSources[i].Screen);
                DerivedDrawInfo.ThermalSources[i].Visible =
                    PointVisible(DerivedDrawInfo.ThermalSources[i].Screen);
            } else {
                DerivedDrawInfo.ThermalSources[i].Visible = false;
            }
        } else {
            DerivedDrawInfo.ThermalSources[i].Visible = false;
        }
    }
}
Example #6
0
void
EstimateThermalBase(const GeoPoint location, const fixed altitude,
                    const fixed average, const SpeedVector wind,
                    GeoPoint &ground_location, fixed &ground_alt)
{
  if (!positive(average))
    return;

  // Time spent in last thermal
  fixed Tmax = altitude / average;

  // Shortcut if no terrain available
  if (terrain == NULL) {
    ground_location = FindLatitudeLongitude(location, wind.bearing,
                                            wind.norm * Tmax);
    ground_alt = fixed_zero;
    return;
  }

  // Time of the 10 calculation intervals
  fixed dt = Tmax / 10;

  RasterTerrain::Lease map(*terrain);

  GeoPoint loc;
  // Iterate over 10 time-based calculation intervals
  for (fixed t = fixed_zero; t <= Tmax; t += dt) {
    // Calculate position
    loc = FindLatitudeLongitude(location, wind.bearing, wind.norm * t);
    // Calculate altitude
    fixed hthermal = altitude - average * t;
    // Calculate altitude above ground
    fixed dh = hthermal - GetElevation(map, loc);

    // Below ground level
    if (negative(dh)) {
      // Calculate time when we passed the ground level
      t = t + dh / average;
      // Calculate position
      loc = FindLatitudeLongitude(location, wind.bearing, wind.norm * t);
      break;
    }
  }

  ground_location = loc;
  ground_alt = GetElevation(map, ground_location);
}
Example #7
0
GeoPoint
ThermalSource::CalculateAdjustedLocation(fixed altitude,
                                         const SpeedVector &wind) const
{
  fixed dh = altitude - ground_height;
  fixed t = dh / lift_rate;
  return FindLatitudeLongitude(location, wind.bearing.Reciprocal(), wind.norm * t);
}
Example #8
0
GeoPoint
TeamCode::GetLocation(const GeoPoint ref) const
{
  Angle bearing = GetBearing();
  fixed distance = GetRange();

  return FindLatitudeLongitude(ref, bearing, distance);
}
Example #9
0
std::ostream& operator<< (std::ostream& f, 
                          const AirspaceCircle& as)
{
  f << "# circle\n";
  for (double t=0; t<=360; t+= 30) {
    GeoPoint l = FindLatitudeLongitude(as.m_center, Angle::Degrees(fixed(t)), as.m_radius);
    f << l.longitude << " " << l.latitude << " " << as.GetBase().altitude << "\n";
  }
  f << "\n";
  for (double t=0; t<=360; t+= 30) {
    GeoPoint l = FindLatitudeLongitude(as.m_center, Angle::Degrees(fixed(t)), as.m_radius);
    f << l.longitude << " " << l.latitude << " " << as.GetTop().altitude << "\n";
  }
  f << "\n";
  f << "\n";
  return f;
}
void
MapWindow::DrawTaskOffTrackIndicator(Canvas &canvas)
{
  if (Calculated().circling 
      || !Basic().location_available
      || !Basic().track_available
      || !GetMapSettings().detour_cost_markers_enabled)
    return;

  const TaskStats &task_stats = Calculated().task_stats;
  const ElementStat &current_leg = task_stats.current_leg;

  if (!task_stats.task_valid || !current_leg.location_remaining.IsValid())
    return;

  const GeoPoint target = current_leg.location_remaining;
  GeoVector vec(Basic().location, target);

  if ((Basic().track - vec.bearing).AsDelta().AbsoluteDegrees() < fixed(10))
    // insignificant error
    return;

  fixed distance_max =
    std::min(vec.distance,
             render_projection.GetScreenDistanceMeters() * fixed(0.7));

  // too short to bother
  if (distance_max < fixed(5000))
    return;

  GeoPoint start = Basic().location;
  
  canvas.Select(*look.overlay_font);
  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundTransparent();
  
  GeoPoint dloc;
  int ilast = 0;
  for (fixed d = fixed(1) / 4; d <= fixed(1); d += fixed(1) / 4) {
    dloc = FindLatitudeLongitude(start, Basic().track, distance_max * d);
    
    fixed distance0 = start.Distance(dloc);
    fixed distance1 = target.Distance(dloc);
    fixed distance = fixed(distance0 + distance1) / vec.distance;
    int idist = iround((distance - fixed(1)) * 100);
    
    if ((idist != ilast) && (idist > 0) && (idist < 1000)) {
      TCHAR Buffer[5];
      _stprintf(Buffer, _T("%d"), idist);
      RasterPoint sc = render_projection.GeoToScreen(dloc);
      PixelSize tsize = canvas.CalcTextSize(Buffer);
      canvas.DrawText(sc.x - tsize.cx / 2, sc.y - tsize.cy / 2, Buffer);
      ilast = idist;
    }
  }
}
Example #11
0
void SimFastForward() {
    if(HasKeyboard()) {
        double gs=GPS_INFO.Speed*10.0;
        if (gs<100) gs=100;
        FindLatitudeLongitude(GPS_INFO.Latitude, GPS_INFO.Longitude, 
                          GPS_INFO.TrackBearing, gs,
                          &GPS_INFO.Latitude,
                          &GPS_INFO.Longitude);
    }
}
Example #12
0
static void
CalculateSector(AirspaceDatabase &airspace_database, TCHAR *Text,
                unsigned &NumberOfAirspacePoints)
{
  double Radius;
  double StartBearing;
  double EndBearing;
  TCHAR *Stop;

  Radius = NAUTICALMILESTOMETRES * (double)_tcstod(&Text[2], &Stop);
  StartBearing = (double)_tcstod(&Stop[1], &Stop);
  EndBearing = (double)_tcstod(&Stop[1], &Stop);

  GEOPOINT c; c.Longitude = CenterX; c.Latitude = CenterY;

  while(fabs(EndBearing-StartBearing) > 7.5) {
    if(StartBearing >= 360)
      StartBearing -= 360;
    if(StartBearing < 0)
      StartBearing += 360;

    //	  if (bFillMode)	// Trig calcs not needed on first pass
    {
      FindLatitudeLongitude(c,
                            StartBearing, Radius,
                            &TempPoint);
    }
    AddPoint(airspace_database, &TempPoint, &TempArea.NumPoints,
             NumberOfAirspacePoints);

    StartBearing += Rotation *5 ;
  }

  //  if (bFillMode)	// Trig calcs not needed on first pass
  {
    FindLatitudeLongitude(c, EndBearing, Radius,
                          &TempPoint);
  }
  AddPoint(airspace_database, &TempPoint, &TempArea.NumPoints,
           NumberOfAirspacePoints);
}
Example #13
0
static void
AppendArc(std::vector<GeoPoint> &points, GeoPoint center,
          fixed radius, fixed _step)
{
  Angle start = Angle::Zero();
  Angle end = Angle::HalfCircle();

  // 5 or -5, depending on direction
  const Angle step = Angle::Degrees(_step);

  // Add first polygon point
  points.push_back(FindLatitudeLongitude(center, start, radius));

  // Add intermediate polygon points
  while ((end - start).AbsoluteDegrees() > _step * 3 / 2) {
    start = (start + step).AsBearing();
    points.push_back(FindLatitudeLongitude(center, start, radius));
  }

  // Add last polygon point
  points.push_back(FindLatitudeLongitude(center, end, radius));
}
Example #14
0
static void
CalculateArc(AirspaceDatabase &airspace_database, TCHAR *Text,
             unsigned &NumberOfAirspacePoints)
{
  GEOPOINT Start;
  GEOPOINT End;
  double StartBearing;
  double EndBearing;
  double Radius;
  TCHAR *Comma = NULL;

  ReadCoords(&Text[3],&Start.Longitude , &Start.Latitude);

  Comma = _tcschr(Text,',');
  if(!Comma)
    return;

  ReadCoords(&Comma[1],&End.Longitude , &End.Latitude);

  GEOPOINT c; c.Longitude = CenterX; c.Latitude = CenterY;

  DistanceBearing(c, Start,
                  &Radius, &StartBearing);
  EndBearing = Bearing(c, End);
  TempPoint.Latitude  = Start.Latitude;
  TempPoint.Longitude = Start.Longitude;
  AddPoint(airspace_database, &TempPoint, &TempArea.NumPoints,
           NumberOfAirspacePoints);

  while(fabs(EndBearing-StartBearing) > 7.5) {
    StartBearing += Rotation *5 ;

    if(StartBearing > 360)
      StartBearing -= 360;
    if(StartBearing < 0)
      StartBearing += 360;

    if (bFillMode) { // Trig calcs not needed on first pass
      GEOPOINT c; c.Longitude = CenterX; c.Latitude = CenterY;
      FindLatitudeLongitude(c, StartBearing, Radius,
                            &TempPoint);
    }

    AddPoint(airspace_database, &TempPoint, &TempArea.NumPoints,
             NumberOfAirspacePoints);
  }

  TempPoint  = End;
  AddPoint(airspace_database, &TempPoint, &TempArea.NumPoints,
           NumberOfAirspacePoints);
}
Example #15
0
void
Simulator::Process(NMEAInfo &basic)
{
  assert(is_simulator());

  Touch(basic);

  basic.location = FindLatitudeLongitude(basic.location, basic.track,
                                         basic.ground_speed);

  // use this to test FLARM parsing/display
  if (IsDebug() && !IsAltair())
    GenerateFLARMTraffic(basic);
}
Example #16
0
static void
CalculateSector(const TCHAR *Text, TempAirspaceType &temp_area)
{
  // 5 or -5, depending on direction
  const Angle BearingStep = Angle::degrees(temp_area.Rotation * fixed(5));

  // Determine radius and start/end bearing
  TCHAR *Stop;
  fixed Radius = Units::ToSysUnit(fixed(_tcstod(&Text[2], &Stop)), unNauticalMiles);
  Angle StartBearing = Angle::degrees(fixed(_tcstod(&Stop[1], &Stop))).as_bearing();
  Angle EndBearing = Angle::degrees(fixed(_tcstod(&Stop[1], &Stop))).as_bearing();

  // Add intermediate polygon points
  GeoPoint TempPoint;
  while ((EndBearing - StartBearing).magnitude_degrees() > fixed_7_5) {
    TempPoint = FindLatitudeLongitude(temp_area.Center, StartBearing, Radius);
    temp_area.points.push_back(TempPoint);
    StartBearing = (StartBearing + BearingStep).as_bearing();
  }

  // Add last polygon point
  TempPoint = FindLatitudeLongitude(temp_area.Center, EndBearing, Radius);
  temp_area.points.push_back(TempPoint);
}
Example #17
0
static void
ScanAirspaceCircleBounds(AirspaceDatabase &airspace_database, int i,
                         double bearing)
{
  AIRSPACE_CIRCLE &circle = airspace_database.AirspaceCircle[i];
  GEOPOINT loc;

  FindLatitudeLongitude(circle.Location,
                        bearing, circle.Radius,
                        &loc);

  circle.bounds.minx = min(loc.Longitude, circle.bounds.minx);
  circle.bounds.maxx = max(loc.Longitude, circle.bounds.maxx);
  circle.bounds.miny = min(loc.Latitude, circle.bounds.miny);
  circle.bounds.maxy = max(loc.Latitude, circle.bounds.maxy);
}
Example #18
0
static bool
ParseArcTNP(const TCHAR *Text, TempAirspaceType &temp_area)
{
  if (temp_area.points.empty())
    return false;

  // (ANTI-)CLOCKWISE RADIUS=34.95 CENTRE=N523333 E0131603 TO=N522052 E0122236

  GeoPoint from = temp_area.points.back();

  const TCHAR* parameter;
  if ((parameter = _tcsstr(Text, _T(" "))) == NULL)
    return false;
  if ((parameter = string_after_prefix_ci(parameter, _T(" CENTRE="))) == NULL)
    return false;
  ParseCoordsTNP(parameter, temp_area.Center);

  GeoPoint to;
  if ((parameter = _tcsstr(parameter, _T(" "))) == NULL)
    return false;
  parameter++;
  if ((parameter = _tcsstr(parameter, _T(" "))) == NULL)
    return false;
  if ((parameter = string_after_prefix_ci(parameter, _T(" TO="))) == NULL)
    return false;
  ParseCoordsTNP(parameter, to);

  Angle bearing_from;
  Angle bearing_to;
  fixed radius;

  static const fixed fixed_75 = fixed(7.5);
  const Angle BearingStep = Angle::degrees(temp_area.Rotation * fixed(5));

  DistanceBearing(temp_area.Center, from, &radius, &bearing_from);
  bearing_to = Bearing(temp_area.Center, to);

  GeoPoint TempPoint;
  while ((bearing_to - bearing_from).magnitude_degrees() > fixed_75) {
    bearing_from += BearingStep;
    bearing_from = bearing_from.as_bearing();
    FindLatitudeLongitude(temp_area.Center, bearing_from, radius, &TempPoint);
    temp_area.points.push_back(TempPoint);
  }

  return true;
}
Example #19
0
static void
CalculateArc(const TCHAR *Text, TempAirspaceType &temp_area)
{
  // 5 or -5, depending on direction
  const Angle BearingStep = Angle::degrees(temp_area.Rotation * fixed(5));

  // Read start coordinates
  GeoPoint Start;
  if (!ReadCoords(&Text[3], Start))
    return;

  // Skip comma character
  const TCHAR* Comma = _tcschr(Text, ',');
  if (!Comma)
    return;

  // Read end coordinates
  GeoPoint End;
  if (!ReadCoords(&Comma[1], End))
    return;

  // Determine start bearing and radius
  Angle StartBearing;
  fixed Radius;
  temp_area.Center.distance_bearing(Start, Radius, StartBearing);

  // Determine end bearing
  Angle EndBearing = Bearing(temp_area.Center, End);

  // Add first polygon point
  GeoPoint TempPoint = Start;
  temp_area.points.push_back(TempPoint);

  // Add intermediate polygon points
  while ((EndBearing - StartBearing).magnitude_degrees() > fixed_7_5) {
    StartBearing = (StartBearing + BearingStep).as_bearing();
    TempPoint = FindLatitudeLongitude(temp_area.Center, StartBearing, Radius);
    temp_area.points.push_back(TempPoint);
  }

  // Add last polygon point
  TempPoint = End;
  temp_area.points.push_back(TempPoint);
}
Example #20
0
void
ThermalLocator::Update(const fixed t_0, 
                       const GeoPoint &location_0,
                       const SpeedVector wind, 
                       ThermalLocatorInfo &therm)
{
  if (n_points < TLOCATOR_NMIN) {
    therm.estimate_valid = false;
    return; // nothing to do.
  }

  GeoPoint dloc = FindLatitudeLongitude(location_0, wind.bearing, wind.norm);

  TaskProjection projection;
  projection.reset(location_0);
  projection.update_fast();

  // drift points 
  Drift(t_0, projection, location_0 - dloc);

  FlatPoint av = glider_average();
  // find thermal center relative to glider's average position

  FlatPoint f0(fixed_zero, fixed_zero);
  fixed acc = fixed_zero;
  for (unsigned i = 0; i < n_points; ++i) {
    f0 += (points[i].loc_drift-av)*points[i].lift_weight;
    acc += points[i].lift_weight;
  }

  // if sufficient data, estimate location

  if (!positive(acc)) {
    therm.estimate_valid = false;
    return;
  }
  f0 = f0 * (fixed_one/acc) + av;

  therm.estimate_location = projection.funproject(f0);
  therm.estimate_valid = true;
}
Example #21
0
void
TrackLineRenderer::DrawProjected(Canvas &canvas,
                                 const WindowProjection &projection,
                                 const NMEAInfo &basic,
                                 const DerivedInfo &calculated,
                                 const MapSettings &settings,
                                 bool wind_relative)
{
  // projection.GetMapScale() <= 6000;

  GeoPoint traildrift;

  if (calculated.wind_available && !wind_relative) {
    GeoPoint tp1 = FindLatitudeLongitude(basic.location,
                                         calculated.wind.bearing,
                                         calculated.wind.norm);
    traildrift = basic.location - tp1;
  } else {
    traildrift = GeoPoint(Angle::Zero(), Angle::Zero());
  }

  auto dt = ARC_SWEEP/ARC_STEPS/
    std::max(MIN_RATE,calculated.turn_rate_heading_smoothed.Absolute());

  Angle heading = basic.attitude.heading;
  GeoPoint loc = basic.location;

  RasterPoint pts[ARC_STEPS+1];
  pts[0] = projection.GeoToScreen(loc);
  int i = 1;

  while (i <= ARC_STEPS) {
    GeoVector v(basic.true_airspeed*dt, heading);
    loc = v.EndPoint(loc.Parametric(traildrift, dt));
    pts[i] = projection.GeoToScreen(loc);
    heading += calculated.turn_rate_heading_smoothed*dt;
    i++;
  }
  canvas.Select(look.track_line_pen);
  canvas.DrawPolyline(pts, i);
}
Example #22
0
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();
}
Example #23
0
double FindInsideAATSectorDistance(double latitude,
                                   double longitude,
                                   int taskwaypoint, 
                                   double course_bearing,
                                   double p_found) {

  double max_distance;
  if(Task[taskwaypoint].AATType == SECTOR) {
    max_distance = Task[taskwaypoint].AATSectorRadius;
  } else {
    max_distance = Task[taskwaypoint].AATCircleRadius;
  }

  // Do binary bounds search for longest distance within sector

  double delta = max_distance;
  double t_distance_lower = p_found;
  double t_distance = p_found+delta*2;
  int steps = 0;
  do {

    double t_lat, t_lon;
    FindLatitudeLongitude(latitude, longitude, 
                          course_bearing, t_distance,
                          &t_lat, &t_lon);

    if (InAATTurnSector(t_lon, t_lat, taskwaypoint, 0)) {
      t_distance_lower = t_distance;
      // ok, can go further
      t_distance += delta;
    } else {
      t_distance -= delta;
    }
    delta /= 2.0;
  } while ((delta>5.0)&&(steps++<20));

  return t_distance_lower;
}
Example #24
0
  void
  AppendArc(const GeoPoint start, const GeoPoint end)
  {

    // Determine start bearing and radius
    const GeoVector v = center.DistanceBearing(start);
    Angle start_bearing = v.bearing;
    const fixed radius = v.distance;

    // 5 or -5, depending on direction
    const auto _step = ArcStepWidth(radius);
    const Angle step = Angle::Degrees(rotation * _step);
    const fixed threshold = _step * fixed(1.5);

    // Determine end bearing
    Angle end_bearing = center.Bearing(end);

    if (rotation > 0) {
      while (end_bearing < start_bearing)
        end_bearing += Angle::FullCircle();
    } else if (rotation < 0) {
      while (end_bearing > start_bearing)
        end_bearing -= Angle::FullCircle();
    }

    // Add first polygon point
    points.push_back(start);

    // Add intermediate polygon points
    while ((end_bearing - start_bearing).AbsoluteDegrees() > threshold) {
      start_bearing += step;
      points.push_back(FindLatitudeLongitude(center, start_bearing, radius));
    }

    // Add last polygon point
    points.push_back(end);
  }
Example #25
0
double FindInsideAATSectorDistance_old(double latitude,
                                       double longitude,
                                       int taskwaypoint, 
                                       double course_bearing,
                                       double p_found) {
  bool t_in_sector;
  double delta;
  double max_distance;
  if(Task[taskwaypoint].AATType == SECTOR) {
    max_distance = Task[taskwaypoint].AATSectorRadius*2;
  } else {
    max_distance = Task[taskwaypoint].AATCircleRadius*2;
  }
  delta = max(250.0, max_distance/40.0);

  double t_distance = p_found;
  double t_distance_inside;

  do {
    double t_lat, t_lon;
    t_distance_inside = t_distance;
    t_distance += delta;

    FindLatitudeLongitude(latitude, longitude, 
                          course_bearing, t_distance,
                          &t_lat,
                          &t_lon);
    
    t_in_sector = InAATTurnSector(t_lon,
                                  t_lat,
                                  taskwaypoint, 0);

  } while (t_in_sector);

  return t_distance_inside;
}
Example #26
0
void
Simulator::Process(NMEAInfo &basic)
{
  if (!is_simulator())
    return;

  basic.UpdateClock();
  basic.connected.Update(basic.clock);
  basic.gps.satellites_used = -1;
  basic.gps.simulator = true;
  basic.gps.real = false;

#ifdef ANDROID
  basic.gps.android_internal_gps = false;
#endif

  basic.location = FindLatitudeLongitude(basic.location, basic.track,
                                         basic.ground_speed);
  basic.location_available.Update(basic.clock);
  basic.gps_altitude_available.Update(basic.clock);
  basic.track_available.Update(basic.clock);
  basic.ground_speed_available.Update(basic.clock);

  basic.time_available.Update(basic.clock);
  basic.time += fixed_one;
  (BrokenTime &)basic.date_time_utc =
    BrokenTime::FromSecondOfDayChecked((unsigned)basic.time);

  // use this to test FLARM parsing/display
  if (is_debug() && !is_altair())
    GenerateFLARMTraffic(basic);

  // clear Airspeed as it is not available in simulation mode
  basic.airspeed_available.Clear();
  basic.airspeed_real = false;
}
Example #27
0
static void
CalculateArc(const TCHAR *Text, TempAirspaceType &temp_area)
{
  GeoPoint Start;
  GeoPoint End;
  Angle StartBearing;
  fixed Radius;
  const TCHAR *Comma = NULL;
  GeoPoint TempPoint;
  static const fixed fixed_75 = fixed(7.5);
  const Angle BearingStep = Angle::degrees(temp_area.Rotation * fixed(5));

  ReadCoords(&Text[3], Start);

  Comma = _tcschr(Text, ',');
  if (!Comma)
    return;

  ReadCoords(&Comma[1], End);

  DistanceBearing(temp_area.Center, Start, &Radius, &StartBearing);
  Angle EndBearing = Bearing(temp_area.Center, End);
  TempPoint.Latitude = Start.Latitude;
  TempPoint.Longitude = Start.Longitude;
  temp_area.points.push_back(TempPoint);

  while ((EndBearing - StartBearing).magnitude_degrees() > fixed_75) {
    StartBearing += BearingStep;
    StartBearing = StartBearing.as_bearing();
    FindLatitudeLongitude(temp_area.Center, StartBearing, Radius, &TempPoint);
    temp_area.points.push_back(TempPoint);
  }

  TempPoint = End;
  temp_area.points.push_back(TempPoint);
}
Example #28
0
void WhereAmI::run(void) {

#ifdef TESTBENCH
    StartupStore(_T("Oracle : start to find position") NEWLINE);
#endif

    PeriodClock _time;
    _time.Update();

    ResetNearestTopology();

    LockTerrainDataGraphics();

    const vectorObj center = {
        MapWindow::GetPanLongitude(),
        MapWindow::GetPanLatitude()
    };
    rectObj bounds = {
        center.x, center.y,
        center.x, center.y
    };

    for(int i = 0; i < 10; ++i) {
        double X, Y;
        FindLatitudeLongitude(center.y, center.x, i*360/10, 30*1000, &Y, &X );
        bounds.minx = std::min(bounds.minx, X);
        bounds.maxx = std::max(bounds.maxx, X);
        bounds.miny = std::min(bounds.miny, Y);
        bounds.maxy = std::max(bounds.maxy, Y);
    }


    for (int z=0; z<MAXTOPOLOGY; z++) {
        if (TopoStore[z]) {
            // See also CheckScale for category checks! We should use a function in fact.
            if ( TopoStore[z]->scaleCategory == 10 ||
                    (TopoStore[z]->scaleCategory >= 70 && TopoStore[z]->scaleCategory <=100)) {
                TopoStore[z]->SearchNearest(bounds);
            }
        }
    }

    TCHAR ttmp[100];
    double dist,wpdist,brg;
    NearestTopoItem *item=NULL;
    bool found=false, over=false, saynear=false, needmorewp=false, secondwpdone=false;

#if TESTBENCH
    if (NearestBigCity.Valid)
        StartupStore(_T("... NEAREST BIG CITY <%s>  at %.0f km brg=%.0f\n"),
                     NearestBigCity.Name,NearestBigCity.Distance/1000,NearestBigCity.Bearing);
    if (NearestCity.Valid)
        StartupStore(_T("... NEAREST CITY <%s>  at %.0f km brg=%.0f\n"),
                     NearestCity.Name,NearestCity.Distance/1000,NearestCity.Bearing);
    if (NearestSmallCity.Valid)
        StartupStore(_T("... NEAREST TOWN <%s>  at %.0f km brg=%.0f\n"),
                     NearestSmallCity.Name,NearestSmallCity.Distance/1000,NearestSmallCity.Bearing);
    if (NearestWaterArea.Valid)
        StartupStore(_T("... NEAREST WATER AREA <%s>  at %.0f km brg=%.0f\n"),
                     NearestWaterArea.Name,NearestWaterArea.Distance/1000,NearestWaterArea.Bearing);
#endif


    _stprintf(toracle,_T("%s\n\n"), MsgToken(1724)); // YOUR POSITION:

    if (NearestBigCity.Valid) {
        _tcscat(toracle, OracleFormatDistance(NearestBigCity.Name,MsgToken(1714),
                                              NearestBigCity.Distance, NearestBigCity.Bearing,0));	// the city
        _tcscat(toracle, _T("\n"));
    }


    if (NearestCity.Valid && NearestSmallCity.Valid) {

        if ( (NearestCity.Distance - NearestSmallCity.Distance) <=3000)
            item=&NearestCity;
        else
            item=&NearestSmallCity;
    } else {
        if (NearestCity.Valid)
            item=&NearestCity;
        else if (NearestSmallCity.Valid)
            item=&NearestSmallCity;
    }

    if (item) {
        dist=item->Distance;
        brg=item->Bearing;

        if (dist>1500) {
            //
            // 2km South of city
            //
            _stprintf(ttmp,_T("%.0f %s %s %s "), dist*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg),
                      MsgToken(1715));	// of the city
            _tcscat(toracle,ttmp);

        } else {
            //
            //  Over city
            //
            _stprintf(ttmp,_T("%s "),MsgToken(1716)); // Over the city
            _tcscat(toracle,ttmp);
            over=true;
        }
        _stprintf(ttmp,_T("<%s>"), item->Name);
        _tcscat(toracle,ttmp);

        found=true;
    }

    // Careful, some wide water areas have the center far away from us even if we are over them.
    // We can only check for 2-5km distances max.
    if (NearestWaterArea.Valid) {
        if (found) {
            if (NearestWaterArea.Distance<2000) {
                if (over) {
                    //
                    // Over city and lake
                    //
                    _stprintf(ttmp,_T(" %s %s"), MsgToken(1717),NearestWaterArea.Name); // and
                    _tcscat(toracle,ttmp);
                    saynear=true;
                } else {
                    //
                    // 2km South of city
                    // over lake
                    //
                    _stprintf(ttmp,_T("\n%s %s"), MsgToken(1718),NearestWaterArea.Name); // over
                    _tcscat(toracle,ttmp);
                    saynear=true;
                }
            } else {
                if (NearestWaterArea.Distance<6000) {
                    if (over) {
                        //
                        // Over city
                        // near lake
                        //
                        _stprintf(ttmp,_T("\n%s %s"), MsgToken(1719),NearestWaterArea.Name); // near to
                        _tcscat(toracle,ttmp);
                    } else {
                        //
                        // 2km South of city
                        // near lake
                        //
                        _stprintf(ttmp,_T("\n%s %s"), MsgToken(1718),NearestWaterArea.Name); // over
                        _tcscat(toracle,ttmp);
                    }
                }
                // else no mention to water area, even if it is the only item. Not accurate!
            }
        } else {
            if (NearestWaterArea.Distance>2000) {
                brg=NearestWaterArea.Bearing;
                //
                // 2km North of lake
                //
                _stprintf(ttmp,_T("%.0f %s %s "), NearestWaterArea.Distance*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg));
                _tcscat(toracle,ttmp);
                _stprintf(ttmp,_T("%s <%s>"), MsgToken(1711),NearestWaterArea.Name); // of
                _tcscat(toracle,ttmp);
            } else {
                //
                // Over lake
                //
                _stprintf(ttmp,_T("%s <%s>"), MsgToken(1718),NearestWaterArea.Name); // over
                _tcscat(toracle,ttmp);
                over=true;
            }
            found=true;
        }
    }

    _tcscat(toracle,_T("\n"));


    // find nearest turnpoint & nearest Landable
    unsigned idx_nearest_airport = 0;
    unsigned idx_nearest_unknown = 0;
    {
        double dist_airport = std::numeric_limits<double>::max();
        double dist_unknown = std::numeric_limits<double>::max();

        for(unsigned i=NUMRESWP; i<WayPointList.size(); ++i) {

            if(WayPointList[i].Style == STYLE_THERMAL) continue;

            DistanceBearing(GPS_INFO.Latitude, GPS_INFO.Longitude,
                            WayPointList[i].Latitude, WayPointList[i].Longitude,
                            &(WayPointCalc[i].Distance), &(WayPointCalc[i].Bearing));

            if(WayPointCalc[i].Distance > 70000) continue; // To Far

            if(WayPointCalc[i].WpType == WPT_AIRPORT) {
                if(WayPointCalc[i].Distance < dist_airport) {
                    dist_airport = WayPointCalc[i].Distance;
                    idx_nearest_airport = i;
                }
            }
            if(WayPointCalc[i].Distance < dist_unknown) {
                dist_unknown = WayPointCalc[i].Distance;
                idx_nearest_unknown = i;
            }
        }
    }

    int j = idx_nearest_unknown;
    if (!ValidNotResWayPoint(j)) goto _end;

    found=true;

_dowp:

    DistanceBearing(
        WayPointList[j].Latitude,WayPointList[j].Longitude,
        GPS_INFO.Latitude, GPS_INFO.Longitude,
        &wpdist,&brg);

    TCHAR wptype[100];
    switch(WayPointList[j].Style) {
    case STYLE_AIRFIELDGRASS:
    case STYLE_GLIDERSITE:
        _stprintf(wptype,_T("%s "), MsgToken(1720));	// the airfield of
        break;
    case STYLE_OUTLANDING:
        _stprintf(wptype,_T("%s "), MsgToken(1721));	// the field of
        needmorewp=true;
        break;
    case STYLE_AIRFIELDSOLID:
        _stprintf(wptype,_T("%s "), MsgToken(1722));	// the airport of
        break;
    default:
        _tcscpy(wptype,_T(""));
        needmorewp=true;
        break;
    }

    if ( (_tcslen(wptype)==0) && WayPointCalc[j].IsLandable) {
        if (WayPointCalc[j].IsAirport)  {
            _stprintf(wptype,_T("%s "), MsgToken(1720));	// the airfield of
            needmorewp=false;
        } else {
            _stprintf(wptype,_T("%s "), MsgToken(1721));	// the field of
            needmorewp=true;
        }
    } else {
        if (_tcslen(wptype)==0 ) {
            _tcscpy(wptype,_T(""));
            needmorewp=true;
        }
    }

    // nn km south
    if (wpdist>2000) {
        //
        // 2km South of city
        // and/over lake
        // 4 km SW of waypoint
        _stprintf(ttmp,_T("\n%.0f %s %s "), wpdist*DISTANCEMODIFY, Units::GetDistanceName(), DegreesToText(brg));
        _tcscat(toracle,ttmp);

        _stprintf(ttmp,_T("%s %s<%s>"), MsgToken(1711),wptype,WayPointList[j].Name); // of
        _tcscat(toracle,ttmp);

    } else {
        if (found) {
            if (over) {
                if (saynear) {
                    //
                    // 2km South of city
                    // over lake
                    // near waypoint
                    // ----
                    // Over city and lake
                    // near waypoint

                    _stprintf(ttmp,_T("\n%s %s<%s>"), MsgToken(1719),wptype,WayPointList[j].Name); // near to
                    _tcscat(toracle,ttmp);
                } else {
                    // Over city
                    // near lake and waypoint

                    _stprintf(ttmp,_T(" %s %s<%s>"), MsgToken(1717),wptype,WayPointList[j].Name); // and
                    _tcscat(toracle,ttmp);
                }
            } else {
                _stprintf(ttmp,_T("\n%s %s<%s>"), MsgToken(1719),wptype,WayPointList[j].Name); // near to
                _tcscat(toracle,ttmp);
            }
        } else {
            //
            // Near waypoint (because "over" could be wrong, we have altitudes in wp!)
            //
            _stprintf(ttmp,_T("%s %s<%s>"), MsgToken(1723),wptype,WayPointList[j].Name); // Near to
            _tcscat(toracle,ttmp);
        }
    }

    if (!needmorewp) goto _end;
    if (secondwpdone) goto _end;

    j=idx_nearest_airport;
    if (!ValidNotResWayPoint(j)) goto _end;
    secondwpdone=true;
    goto _dowp;

_end:

    UnlockTerrainDataGraphics();

#ifdef ULLIS_PRIVATE_FEATURES
    _stprintf(ttmp,_T("\n\nin %i ft (MSL)"),  (int)( GPS_INFO.Altitude*TOFEET)); // in height
    _tcscat(toracle,ttmp);
#endif
    // VERY SORRY - YOUR POSITION IS UNKNOWN!
    if (!found) _stprintf(toracle,_T("\n\n%s\n\n%s"), MsgToken(1725),MsgToken(1726));

    CharUpper(toracle);

#ifdef TESTBENCH
    StartupStore(_T("Oracle : Result found in %d ms") NEWLINE, _time.Elapsed());
#endif
}
Example #29
0
void Statistics::RenderTask(LKSurface& Surface, const RECT& rc, const bool olcmode)
{
  int i, j;
  unsigned int ui;
double fXY_Scale = 1.5;
  double lat1 = 0;
  double lon1 = 0;
  double lat2 = 0;
  double lon2 = 0;
  double x1, y1, x2=0, y2=0;
  double lat_c, lon_c;
  double aatradius[MAXTASKPOINTS];

  // find center
  ResetScale();

  if ( (!ValidTaskPoint(0) || !ValidTaskPoint(1)) && !olcmode)
  {
	DrawNoData(Surface,rc);
	return;
  }

  for (i=0; i<MAXTASKPOINTS; i++)
  {
    aatradius[i]=0;
  }
  bool nowaypoints = true;

  for (i=0; i<MAXTASKPOINTS; i++)
  {
    if (ValidTaskPoint(i))
    {
      lat1 = WayPointList[Task[i].Index].Latitude;
      lon1 = WayPointList[Task[i].Index].Longitude;
      ScaleYFromValue(rc, lat1);
      ScaleXFromValue(rc, lon1);
      nowaypoints = false;
    }
  }

  if (nowaypoints )
  {
    DrawNoData(Surface, rc);
    return;
  }

  CPointGPSArray trace;
  CContestMgr::Instance().Trace(trace);
  for(ui=0; ui<trace.size(); ui++)
  {
    lat1 = trace[ui].Latitude();
    lon1 = trace[ui].Longitude();
    ScaleYFromValue(rc, lat1);
    ScaleXFromValue(rc, lon1);
  }
  const auto hfOldU = Surface.SelectObject(LK8InfoNormalFont);

  lat_c = (y_max+y_min)/2;
  lon_c = (x_max+x_min)/2;

  int nwps = 0;

  // find scale
  ResetScale();

  lat1 = GPS_INFO.Latitude;
  lon1 = GPS_INFO.Longitude;
  x1 = (lon1-lon_c)*fastcosine(lat1);
  y1 = (lat1-lat_c);
  ScaleXFromValue(rc, x1*fXY_Scale);
  ScaleYFromValue(rc, y1*fXY_Scale);



  for (i=0; i<MAXTASKPOINTS; i++)
  {
    if (ValidTaskPoint(i))
    {
      nwps++;
      lat1 = WayPointList[Task[i].Index].Latitude;
      lon1 = WayPointList[Task[i].Index].Longitude;
      x1 = (lon1-lon_c)*fastcosine(lat1);
      y1 = (lat1-lat_c);
      ScaleXFromValue(rc, x1*fXY_Scale);
      ScaleYFromValue(rc, y1*fXY_Scale);

      if (AATEnabled)
      {
	    double aatlat;
	    double aatlon;
	    double bearing;
	    double radius;

        if (ValidTaskPoint(i+1))
        {
          if (Task[i].AATType == SECTOR)
            radius = Task[i].AATSectorRadius;
          else
            radius = Task[i].AATCircleRadius;

          for (j=0; j<4; j++)
          {
            bearing = j*360.0/4;
            FindLatitudeLongitude(WayPointList[Task[i].Index].Latitude, WayPointList[Task[i].Index].Longitude, bearing, radius,  &aatlat, &aatlon);
            x1 = (aatlon-lon_c)*fastcosine(aatlat);
            y1 = (aatlat-lat_c);
            ScaleXFromValue(rc, x1);
            ScaleYFromValue(rc, y1);
            if (j==0)
            {
              aatradius[i] = fabs(aatlat-WayPointList[Task[i].Index].Latitude);
            }
          }
        }
        else
        {
          aatradius[i] = 0;
        }
      }
    }
  }


  for(ui=0; ui<trace.size(); ui++)
  {
    lat1 = trace[ui].Latitude();
    lon1 = trace[ui].Longitude();
    x1 = (lon1-lon_c)*fastcosine(lat1);
    y1 = (lat1-lat_c);
    ScaleXFromValue(rc, x1*fXY_Scale);
    ScaleYFromValue(rc, y1*fXY_Scale);
  }

  ScaleMakeSquare(rc);


  // draw aat areas
    if (AATEnabled)
    {
      for (i=MAXTASKPOINTS-1; i>0; i--)
      {
	    if (ValidTaskPoint(i))
	    {
		  lat1 = WayPointList[Task[i-1].Index].Latitude;
		  lon1 = WayPointList[Task[i-1].Index].Longitude;
		  lat2 = WayPointList[Task[i].Index].Latitude;
		  lon2 = WayPointList[Task[i].Index].Longitude;
		  x1 = (lon1-lon_c)*fastcosine(lat1);
		  y1 = (lat1-lat_c);
		  x2 = (lon2-lon_c)*fastcosine(lat2);
		  y2 = (lat2-lat_c);

#ifdef HAVE_HATCHED_BRUSH 
		  Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(AATASK));
#else
                  Surface.SelectObject(LKBrush_Yellow);
#endif
		  Surface.SelectObject(LK_WHITE_PEN);
		  if (Task[i].AATType == SECTOR)
		  {
			Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc,	Task[i].AATStartRadial,	Task[i].AATFinishRadial);
		  }
		  else
		  {
	        Surface.DrawCircle((long)((x2-x_min)*xscale+rc.left+BORDER_X), (long)((y_max-y2)*yscale+rc.top),  (long)(aatradius[i]*yscale), true);
	      }
        }
      }
    }

  if (!AATEnabled)
  {
	for (i=MAXTASKPOINTS-1; i>0; i--)
	{
	  if (ValidTaskPoint(i) && ValidTaskPoint(i-1))
	  {
		lat1 = WayPointList[Task[i-1].Index].Latitude;
		lon1 = WayPointList[Task[i-1].Index].Longitude;
		if (!ValidTaskPoint(1) ) {
		  lat2 = GPS_INFO.Latitude;
		  lon2 = GPS_INFO.Longitude;
		}
		else
		{
		  lat2 = WayPointList[Task[i].Index].Latitude;
		  lon2 = WayPointList[Task[i].Index].Longitude;
		}
		x1 = (lon1-lon_c)*fastcosine(lat1);
		y1 = (lat1-lat_c);
		x2 = (lon2-lon_c)*fastcosine(lat2);
		y2 = (lat2-lat_c);

	//	DrawLine(hdc, rc, x1, y1, x2, y2, STYLE_DASHGREEN);
		if( ValidTaskPoint(4) && i <2)
			goto skip_FAI;
#ifndef UNDITHER
		RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW );
	    RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN   );
#else
		RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY );
	    RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY   );
#endif
	    skip_FAI:
		DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_DASHGREEN);
		Surface.Segment((long)((x2-x_min)*xscale+rc.left+BORDER_X),(long)((y_max-y2)*yscale+rc.top),(long)(aatradius[i]*yscale),rc,	Task[i].AATStartRadial,	Task[i].AATFinishRadial);
	  }
	}

	if(	 ValidTaskPoint(1) && ValidTaskPoint(3))
	{
	  lat1 = WayPointList[Task[3].Index].Latitude;
	  lon1 = WayPointList[Task[3].Index].Longitude;
	  lat2 = WayPointList[Task[1].Index].Latitude;
	  lon2 = WayPointList[Task[1].Index].Longitude;
          #ifndef UNDITHER
	  RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTYELLOW );
	  RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_LIGHTCYAN   );
          #else
	  RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,1, RGB_LIGHTGREY );
	  RenderFAISector ( Surface, rc, lat1, lon1, lat2, lon2, lat_c, lon_c,0, RGB_GREY   );
          #endif
	}
  }
	// draw task lines and label
	for (i=MAXTASKPOINTS-1; i>0; i--)
	{
	  if (ValidTaskPoint(i) && ValidTaskPoint(i-1))
	  {
		lat1 = WayPointList[Task[i-1].Index].Latitude;
		lon1 = WayPointList[Task[i-1].Index].Longitude;
		if (!ValidTaskPoint(1) ) {
		  lat2 = GPS_INFO.Latitude;
		  lon2 = GPS_INFO.Longitude;
		}
		else
		{
		  lat2 = WayPointList[Task[i].Index].Latitude;
		  lon2 = WayPointList[Task[i].Index].Longitude;
		}
		x1 = (lon1-lon_c)*fastcosine(lat1);
		y1 = (lat1-lat_c);
		x2 = (lon2-lon_c)*fastcosine(lat2);
		y2 = (lat2-lat_c);

		DrawLine(Surface, rc, x1, y1, x2, y2, STYLE_BLUETHIN);
                #if (WINDOWSPC>0)
	    Surface.SetBackgroundOpaque();
                #endif
		TCHAR text[100];
		 Surface.SetTextColor(RGB_BLUE);
/*
		if ((i==nwps-1) && (Task[i].Index == Task[0].Index))
		{
		  _stprintf(text,TEXT("%0d"),1);
		  DrawLabel(hdc, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2);
		}
		else */
		{
		  _stprintf(text,TEXT("%0d"),i);
		  DrawLabel(Surface, rc, text, x1+(x2-x1)/2, y1+(y2-y1)/2);
		}

		if ((i==ActiveTaskPoint)&&(!AATEnabled))
		{
		  lat1 = GPS_INFO.Latitude;
		  lon1 = GPS_INFO.Longitude;
		  x1 = (lon1-lon_c)*fastcosine(lat1);
		  y1 = (lat1-lat_c);
		  DrawLine(Surface, rc, x1, y1, x2, y2,  STYLE_REDTHICK);
		}
	  }
	}
	
	// draw aat task line
	
	if (AATEnabled)
	{
	  for (i=MAXTASKPOINTS-1; i>0; i--)
	  {
		if (ValidTaskPoint(i) && ValidTaskPoint(i-1))
		{
		  if (i==1)
		  {
			lat1 = WayPointList[Task[i-1].Index].Latitude;
			lon1 = WayPointList[Task[i-1].Index].Longitude;
		  }
		  else
		  {
			lat1 = Task[i-1].AATTargetLat;
			lon1 = Task[i-1].AATTargetLon;
		  }
		  lat2 = Task[i].AATTargetLat;
		  lon2 = Task[i].AATTargetLon;
	
		  x1 = (lon1-lon_c)*fastcosine(lat1);
		  y1 = (lat1-lat_c);
		  x2 = (lon2-lon_c)*fastcosine(lat2);
		  y2 = (lat2-lat_c);

		  DrawLine(Surface, rc,   x1, y1, x2, y2,  STYLE_REDTHICK);
		}
	  }
	}

	  DrawXGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false);
	  DrawYGrid(Surface, rc, 1.0, 0, STYLE_THINDASHPAPER, 1.0, false);


  Surface.SelectObject(hfOldU);
  // Draw aircraft on top
  lat1 = GPS_INFO.Latitude;
  lon1 = GPS_INFO.Longitude;
  x1 = (lon1-lon_c)*fastcosine(lat1);
  y1 = (lat1-lat_c);
  Surface.SetBackgroundTransparent();
  DrawLabel(Surface, rc, TEXT("+"), x1, y1);
}
Example #30
0
//
// LK8000 SS1 = Soaring Simulator V1 by Paolo Ventafridda
// Still basic, but usable
//
void LKSimulator(void) {

  LockFlightData();

  // 
  GPS_INFO.NAVWarning = false;
  GPS_INFO.SatellitesUsed = 6;
  // Even on ground, we can turn the glider in the hangar
  BEARING += SimTurn; 
  if (BEARING<0) BEARING+=360;
  else if (BEARING>359) BEARING-=360;

  #if SIMLANDING
  static bool crashed=false, landedwarn=true;
  #endif
  static bool doinit=true, landing=false, stallwarn=true, circling=false, flarmwasinit=false;
  static short counter=0;

  double tdistance, tbearing;
  double thermalstrength=0, sinkstrength=0;

  extern void SimFlarmTraffic(long id, double offset);

  if (doinit) {
	if (counter++<4) {
		UnlockFlightData();
		return;
	}
	#if TESTBENCH
	StartupStore(_T(". SIMULATOR: real init%s"),NEWLINE);
	#endif

	// Add a couple of thermals for the boys
	InsertThermalHistory(GPS_INFO.Time-1887, GPS_INFO.Latitude-0.52, GPS_INFO.Longitude-0.52, 873, 1478,1.5);
	InsertThermalHistory(GPS_INFO.Time-987, GPS_INFO.Latitude-0.41, GPS_INFO.Longitude-0.41, 762, 1367,1.8);
	InsertThermalHistory(GPS_INFO.Time-100, GPS_INFO.Latitude-0.02, GPS_INFO.Longitude-0.02, 650, 1542,2.2);
	WayPointList[RESWP_LASTTHERMAL].Latitude  = GPS_INFO.Latitude-0.022;
	WayPointList[RESWP_LASTTHERMAL].Longitude = GPS_INFO.Longitude-0.022;
	WayPointList[RESWP_LASTTHERMAL].Altitude  = 650;
	ThLatitude=GPS_INFO.Latitude-0.022;
	ThLongitude=GPS_INFO.Longitude-0.022;

	if (EnableFLARMMap) {
		srand( GetTickCount());
		SimFlarmTraffic(0xdd8951,22.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8944,31.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8a43,16.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8a42,41.0+(double)(rand()/1000.0));
	}
	doinit=false;
  }

  // First Aircraft min altitude is at ground level
  if (ALTITUDE==0)
	if (CALCULATED_INFO.TerrainValid) ALTITUDE= CALCULATED_INFO.TerrainAlt;


  if (ISGAAIRCRAFT) {
	// todo: fuel consumption, engine efficiency etc.
  }

  // We cannot use doinit for flarm, because it could be enabled from configuration AFTER startup,
  // and it must work all the way the same in order not to confuse users.
  if (EnableFLARMMap) {
	if (!flarmwasinit) {
		srand( GetTickCount());
		// Add a poker of traffic for the boys
		SimFlarmTraffic(0xdd8951,22.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8944,31.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8a43,16.0+(double)(rand()/1000.0));
		SimFlarmTraffic(0xdd8a42,41.0+(double)(rand()/1000.0));
		DoStatusMessage(gettext(TEXT("[email protected]_"))); // FLARM DETECTED (in sim)
		flarmwasinit=true;
	} else {
		// Let one of the objects be a ghost and a zombie, and keep the rest real
		SimFlarmTraffic(0xdd8951,0);
		SimFlarmTraffic(0xdd8944,0);
		SimFlarmTraffic(0xdd8a43,0);
	}
  }

  if (ISPARAGLIDER || ISGLIDER) {
 
    // SetBallast is calculating sinkratecache for values starting from 4 to MAXSPEED, in m/s .
    // ONLY during flight, we will sink in the air
    if (FLYING && (IASMS>3) && (IASMS<MAXSPEED) ) {

	double sinkias=-1*(GlidePolar::sinkratecache[(int)IASMS]);
	if (sinkias>10) sinkias=10; // set a limiter for sink rate
	// StartupStore(_T(".... ias=%.0f sinkias=%.3f oldAlt=%.3f newAlt=%.3f\n"), 
	// CALCULATED_INFO.IndicatedAirspeedEstimated*TOKPH, sinkias, GPS_INFO.Altitude, GPS_INFO.Altitude+sinkias);
	double simlift=0;
	if (THERMALLING == TRUE) {
		// entering the thermal mode right now
		if (!circling) {
			circling=true;
			
			DistanceBearing(GPS_INFO.Latitude,GPS_INFO.Longitude,ThLatitude,ThLongitude,&tdistance,&tbearing);
			if (tdistance>1000) {
				// a new thermal
				ThLatitude=GPS_INFO.Latitude; // we mark the new thermal
				ThLongitude=GPS_INFO.Longitude;
				ALTITUDE+=simlift; // sink rate adjusted later
			} else {
				// start circling near the old thermal
			}
		} else {
			// already thermalling
		}
		// ALTITUDE+=simlift+GlidePolar::minsink;
	} else {
		if (circling) {
			// we were circling, now leaving the thermal
			circling=false;
		} else {
			// not circling, already cruising
		}
	}

	// Are we near the thermal?
	DistanceBearing(GPS_INFO.Latitude,GPS_INFO.Longitude,ThLatitude,ThLongitude,&tdistance,&tbearing);
	thermalstrength=4; // m/s
	ThermalRadius=200; // we assume a perfect thermal, a circle of this diameter. Stronger in the center.
	// thermalbase
	sinkstrength=2; //  how intense is the fallout of the thermal
	SinkRadius=150; //  circular ring of the fallout

	if (tdistance>=ThermalRadius && tdistance<(ThermalRadius+SinkRadius) ) {
		// we are in the sinking zone of the thermal..
		simlift= sinkstrength- ((tdistance-ThermalRadius)/SinkRadius)*sinkstrength;
		simlift+=0.1; // adjust rounding errors
		simlift*=-1;
		//StartupStore(_T(".. sinking zone:  dist=%.1f  sink=%.1f\n"), tdistance,simlift);
	}
	if (tdistance<ThermalRadius) {
		// we are in the lift zone
		simlift= thermalstrength- (tdistance/ThermalRadius)*thermalstrength;
		simlift+=0.1; // adjust rounding errors
		//StartupStore(_T(".. climbing zone:  dist=%.1f  climb=%.1f\n"), tdistance,simlift);
	}
	// Update altitude with the lift or sink, 
	ALTITUDE+=simlift;
	// Update the new altitude with the natural sink, but not going lower than 0
	ALTITUDE-=(sinkias+0.1); // rounding errors require a correction
	if (ALTITUDE<=0) ALTITUDE=0;

	#if SIMLANDING
	if (CALCULATED_INFO.TerrainValid && (CALCULATED_INFO.AltitudeAGL <=20) ) {
		if (IAS <= (MINSPEED+3)) landing=true;
		else {
			// we dont simulate crashing. LK8000 pilots never crash. 
			crashed=true;
		}
	} 
	if (CALCULATED_INFO.TerrainValid && (CALCULATED_INFO.AltitudeAGL >100) ) {
		landing=false;
	}

	if (!landing && CALCULATED_INFO.TerrainValid && (CALCULATED_INFO.AltitudeAGL <=0) ) {
		GPS_INFO.Speed=0;
		landing=true;
		if (landedwarn) {
			DoStatusMessage(_T("YOU HAVE LANDED"));
			landedwarn=false;
		}
	} else landedwarn=true;
	#endif
		
    } 
  } // Glider/Paragliders

  if (FLYING) {
	// simple stall at 1 G
	if (!landing && (IAS<=STALLSPEED && IASMS>3)) {
		if (stallwarn) {
			// DoStatusMessage(_T("STALLING")); // OK, people do not like stalling.
			stallwarn=false;
		}
		#if 0 // DO NOT SIMULATE STALLING NOW
		// GPS_INFO.Speed= (GlidePolar::Vminsink*0.85)+1;
		ALTITUDE-=20;
		if (ALTITUDE<=0) ALTITUDE=0;
		#endif
	} else stallwarn=true;
	#if SIMLANDING
	if (landing || IASMS<4) {
		GPS_INFO.Speed-=GPS_INFO.Speed*0.2;
	}
	if (crashed) {
		GPS_INFO.Speed=0;
	}
	#endif

	if (GS<0) {
		GPS_INFO.Speed=0;
	}
  }


  FindLatitudeLongitude(GPS_INFO.Latitude, GPS_INFO.Longitude, 
                          GPS_INFO.TrackBearing, GPS_INFO.Speed*1.0,
                          &GPS_INFO.Latitude,
                          &GPS_INFO.Longitude);
  GPS_INFO.Time+= 1.0;
  long tsec = (long)GPS_INFO.Time;
  GPS_INFO.Hour = tsec/3600;
  GPS_INFO.Minute = (tsec-GPS_INFO.Hour*3600)/60;
  GPS_INFO.Second = (tsec-GPS_INFO.Hour*3600-GPS_INFO.Minute*60);

  UnlockFlightData();
  }