public PlaneInfo Get(string hex, DateTime at, int ttl) { PlaneInfo plane = null; DateTime to = at; DateTime from = to - new TimeSpan(0, ttl, 0); // return null if not found if (!this.TryGetValue(hex, out plane)) { return(null); } // return null if not in timespan if ((plane.Time < from) || (plane.Time > to)) { return(null); } // create new plane info PlaneInfo info = new PlaneInfo(plane); // estimate new position // change speed to km/h double speed = info.Speed_kmh; // calculate distance after timespan double dist = speed * (at - info.Time).TotalHours; // estimate new position LatLon.GPoint newpos = LatLon.DestinationPoint(info.Lat, info.Lon, info.Track, dist); info.Lat = newpos.Lat; info.Lon = newpos.Lon; info.Time = at; return(info); }
public List <PlaneInfo> GetAll(DateTime at, int ttl) { List <PlaneInfo> l = new List <PlaneInfo>(); DateTime to = at; DateTime from = to - new TimeSpan(0, ttl, 0); lock (this) { foreach (PlaneInfo plane in this.Values) { if ((plane.Time < from) || (plane.Time > to)) { continue; } // create new plane info PlaneInfo info = new PlaneInfo(plane); // estimate new position // change speed to km/h double speed = info.Speed_kmh; // calculate distance after timespan double dist = speed * (at - info.Time).TotalHours; // estimate new position LatLon.GPoint newpos = LatLon.DestinationPoint(info.Lat, info.Lon, info.Track, dist); double d = LatLon.Distance(info.Lat, info.Lon, newpos.Lat, newpos.Lon); info.Lat = newpos.Lat; info.Lon = newpos.Lon; info.Time = at; l.Add(info); } } return(l); }
///<summary> /// Gets a list of aircraft positions at a time. /// Querying the latest position entry per aircraft but not older than ttl back in history /// and estimating the position at given time /// <param name="at">The given time. </param> /// <param name="ttl">"Time To Live": discard positions which are older than ttl [min]. </param> /// /// </summary> public List <AircraftPositionDesignator> AircraftPositionGetAllLatest(DateTime at, int ttl) { List <AircraftPositionDesignator> l = new List <AircraftPositionDesignator>(); int to = SupportFunctions.DateTimeToUNIXTime(at); int from = to - ttl * 60; DataTable Result = db.Select("SELECT Hex, Call, Lat, Lon, Alt, Track, Speed, max(Lastupdated) AS LastUpdated FROM " + AircraftPositionDesignator.TableName + " WHERE LastUpdated >= " + from.ToString() + " AND LastUpdated <= " + to.ToString() + " GROUP BY Hex"); if (!IsValid(Result) || (Result.Rows.Count == 0)) { return(l); } foreach (DataRow row in Result.Rows) { AircraftPositionDesignator ap = new AircraftPositionDesignator(row); //estimate new position // change speed to km/h double speed = ap.Speed * 1.852; // calculate distance after timespan double dist = speed * (at - ap.LastUpdated).TotalHours; // estimate new position LatLon.GPoint newpos = LatLon.DestinationPoint(ap.Lat, ap.Lon, ap.Track, dist); ap.Lat = newpos.Lat; ap.Lon = newpos.Lon; l.Add(ap); } return(l); }
public PlaneInfo(PlaneInfo plane) { this.Ambiguous = plane.Ambiguous; this.Alt = plane.Alt; this.AltDiff = plane.AltDiff; this.Angle = plane.Angle; this.Call = plane.Call; this.Category = plane.Category; this.Comment = plane.Comment; this.Eps1 = plane.Eps1; this.Eps2 = plane.Eps2; this.Theta1 = plane.Theta1; this.Theta2 = plane.Theta2; this.Hex = plane.Hex; this.IntPoint = plane.IntPoint; this.IntQRB = plane.IntQRB; this.Lat = plane.Lat; this.Lon = plane.Lon; this.Manufacturer = plane.Manufacturer; this.Model = plane.Model; this.Potential = plane.Potential; this.Reg = plane.Reg; this.SignalStrength = plane.SignalStrength; this.Speed = plane.Speed; this.Squint = plane.Squint; this.Time = plane.Time; this.Track = plane.Track; this.Type = plane.Type; }
/// <summary> /// Gets an intersection point of a plane (lat, lon, bearing) with the propagation path in a suitable altitude /// </summary> /// <param name="lat">The latitude of the plane.</param> /// <param name="lon">The longitude of the plane.</param> /// <param name="bearing">The bearing of the plane.</param> /// <param name="maxdistance">The maximum allowed distance to return a valid intersection (-1: no limits, 0: automatcally adjuts to path distance /2).</param> /// <returns>The intersection point, if any. Null if no intersection point exists or plane does not have a suitable altitude at intersection point</returns> /// <summary> public IntersectionPoint GetIntersectionPoint(double lat, double lon, double bearing, double maxdistance) { // get an interscetion point with the propagation path LatLon.GPoint p = LatLon.IntersectionPoint(Lat1, Lon1, Bearing12, lat, lon, bearing); if (p == null) { // if not, return null return(null); } // get the minimum altitude a plane must have at intersection point // get both distances to intersection point double dist1 = LatLon.Distance(Lat1, Lon1, p.Lat, p.Lon); double dist2 = LatLon.Distance(Lat2, Lon2, p.Lat, p.Lon); // chek against localobstruction , if any double eps1_min = Math.Max(Eps1_Min, LocalObstruction); // get minimal altitude double min_H = Math.Max(ScoutBase.Core.Propagation.HeightFromEpsilon(h1, dist1, eps1_min, Radius), ScoutBase.Core.Propagation.HeightFromEpsilon(h2, dist2, Eps2_Min, Radius)); double qrb = LatLon.Distance(p.Lat, p.Lon, lat, lon); if (maxdistance < 0) { return(new IntersectionPoint(p.Lat, p.Lon, qrb, min_H, dist1, dist2)); } if ((maxdistance == 0) && (qrb > Distance / 2)) { return(null); } if (qrb < maxdistance) { return(null); } return(new IntersectionPoint(p.Lat, p.Lon, qrb, min_H, dist1, dist2)); }
/// <summary> /// Returns a single info point in a given distance from location 1 /// </summary> /// <param name="lat">The latitude of the plane.</param> /// <returns>The info point.</returns> public PropagationPoint GetInfoPoint(double dist) { if (StepWidth <= 0) { return(null); } // chek against localobstruction , if any double eps1_min = Math.Max(Eps1_Min, LocalObstruction); LatLon.GPoint p = LatLon.DestinationPoint(Lat1, Lon1, Bearing12, dist); return(new PropagationPoint(p.Lat, p.Lon, ScoutBase.Core.Propagation.HeightFromEpsilon(h1, dist, eps1_min, Radius), ScoutBase.Core.Propagation.HeightFromEpsilon(h2, Distance - dist, Eps2_Min, Radius), ScoutBase.Core.Propagation.F1Radius(QRG, Distance, Distance - dist))); }
private void DrawHorizonPoint(int azimuth, HorizonPoint hp, bool closing = false) { Elevation_Polar_Series.Points.Add(new DataPoint(hp.Epsmin / Math.PI * 180.0, azimuth)); pm_Elevation_Polar.InvalidatePlot(true); if (!closing) { Elevation_Cartesian_Series.Points.Add(new DataPoint(azimuth, hp.Epsmin / Math.PI * 180.0)); } pm_Elevation_Cartesian.InvalidatePlot(true); Distance_Polar_Series.Points.Add(new DataPoint(hp.Dist, azimuth)); pm_Distance_Polar.InvalidatePlot(true); if (!closing) { Distance_Cartesian_Series.Points.Add(new DataPoint(azimuth, hp.Dist)); } pm_Distance_Cartesian.InvalidatePlot(true); LatLon.GPoint gp = LatLon.DestinationPoint(Location.Lat, Location.Lon, azimuth, hp.Dist); PointLatLng p = new PointLatLng(gp.Lat, gp.Lon); horizon.Points.Add(p); if (p.Lng < Map_Left) { Map_Left = p.Lng; } if (p.Lng > Map_Right) { Map_Right = p.Lng; } if (p.Lat < Map_Bottom) { Map_Bottom = p.Lat; } if (p.Lat > Map_Top) { Map_Top = p.Lat; } // toggle visible to redraw horizon.IsVisible = false; horizon.IsVisible = true; gm_Horizon.SetZoomToFitRect(RectLatLng.FromLTRB(Map_Left, Map_Top, Map_Right, Map_Bottom)); }
public PropagationPathDesignator PropagationPathFindOrCreateFromBearing(BackgroundWorker caller, double lat1, double lon1, double h1, double bearing, double distance, double h2, double qrg, double radius, double f1_clearance, double stepwidth, ELEVATIONMODEL model, double localobstruction, bool savetodatabase = true) { LatLon.GPoint gp = LatLon.DestinationPoint(lat1, lon1, bearing, distance); return(PropagationPathFindOrCreateFromLatLon(caller, lat1, lon1, h1, gp.Lat, gp.Lon, h2, qrg, radius, f1_clearance, stepwidth, model, localobstruction, savetodatabase)); }
private void bw_History_DoWork(object sender, DoWorkEventArgs e) { // check that Stepwidth ist positive in any case if (Properties.Settings.Default.Path_History_StepWidth <= 0) { Properties.Settings.Default.Path_History_StepWidth = 1; } bw_History.ReportProgress(0, "Calculating Path...."); LocationDesignator mycall = StationData.Database.LocationFindOrCreate(Properties.Settings.Default.MyCall, MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, false, 3)); QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(mycall.Call, mycall.Loc, Properties.Settings.Default.Band); // set qrv defaults if zero if (myqrv.AntennaHeight == 0) { myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band); } if (myqrv.AntennaGain == 0) { myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band); } if (myqrv.Power == 0) { myqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band); } if (Properties.Settings.Default.Path_BestCaseElevation) { if (!MaidenheadLocator.IsPrecise(mycall.Lat, mycall.Lon, 3)) { ElvMinMaxInfo maxinfo = ElevationData.Database.ElevationTileFindMinMaxInfo(mycall.Loc, Properties.Settings.Default.ElevationModel); if (maxinfo != null) { mycall.Lat = maxinfo.MaxLat; mycall.Lon = maxinfo.MaxLon; } } } LocationDesignator dxcall = StationData.Database.LocationFindOrCreate(Properties.Settings.Default.DXCall, MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3)); QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxcall.Call, dxcall.Loc, Properties.Settings.Default.Band); // set qrv defaults if zero if (dxqrv.AntennaHeight == 0) { dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band); } if (dxqrv.AntennaGain == 0) { dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band); } if (dxqrv.Power == 0) { dxqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band); } if (Properties.Settings.Default.Path_BestCaseElevation) { if (!MaidenheadLocator.IsPrecise(dxcall.Lat, dxcall.Lon, 3)) { ElvMinMaxInfo maxinfo = ElevationData.Database.ElevationTileFindMinMaxInfo(dxcall.Loc, Properties.Settings.Default.ElevationModel); if (maxinfo != null) { dxcall.Lat = maxinfo.MaxLat; dxcall.Lon = maxinfo.MaxLon; } } } // find local obstruction, if any LocalObstructionDesignator o = ElevationData.Database.LocalObstructionFind(mycall.Lat, mycall.Lon, Properties.Settings.Default.ElevationModel); double mybearing = LatLon.Bearing(mycall.Lat, mycall.Lon, dxcall.Lat, dxcall.Lon); double myobstr = (o != null) ? o.GetObstruction(myqrv.AntennaHeight, mybearing) : double.MinValue; // try to find propagation path in database or create new one and store PPath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon( bw_History, mycall.Lat, mycall.Lon, ElevationData.Database[mycall.Lat, mycall.Lon, Properties.Settings.Default.ElevationModel] + myqrv.AntennaHeight, dxcall.Lat, dxcall.Lon, ElevationData.Database[dxcall.Lat, dxcall.Lon, Properties.Settings.Default.ElevationModel] + dxqrv.AntennaHeight, Bands.ToGHz(Properties.Settings.Default.Band), LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor, Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].F1_Clearance, ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel), Properties.Settings.Default.ElevationModel, myobstr); DateTime time = From; lock (Crossings) { Crossings.Clear(); } lock (NearestPositions) { NearestPositions.Clear(); } // pre-select nearest positions only bw_History.ReportProgress(0, "Pre-selecting nearest positions..."); LatLon.GPoint midpoint = PPath.GetMidPoint(); double maxdist = PPath.Distance / 2; foreach (AircraftPositionDesignator ap in AllPositions) { if ((ap.LastUpdated >= From) && (ap.LastUpdated <= To) && (LatLon.Distance(ap.Lat, ap.Lon, midpoint.Lat, midpoint.Lon) <= maxdist)) { AircraftDesignator ac = null; AircraftTypeDesignator at = null; ac = AircraftData.Database.AircraftFindByHex(ap.Hex); if (ac != null) { at = AircraftData.Database.AircraftTypeFindByICAO(ac.TypeCode); } PlaneInfo plane = new PlaneInfo(ap.LastUpdated, ap.Call, ((ac != null) && (!String.IsNullOrEmpty(ac.TypeCode)))? ac.Reg : "[unknown]", ap.Hex, ap.Lat, ap.Lon, ap.Track, ap.Alt, ap.Speed, (ac != null) && (!String.IsNullOrEmpty(ac.TypeCode)) ? ac.TypeCode : "[unkomwn]", ((at != null) && (!String.IsNullOrEmpty(at.Manufacturer))) ? at.Manufacturer : "[unknown]", ((at != null) && (!String.IsNullOrEmpty(at.Model))) ? at.Model : "[unknown]", (at != null) ? at.Category : PLANECATEGORY.NONE); lock (NearestPositions) { NearestPositions.Add(plane); } if (NearestPositions.Count % 1000 == 0) { bw_History.ReportProgress(0, "Pre-selecting nearest positions..." + "[" + NearestPositions.Count.ToString() + "]"); } } if (bw_History.CancellationPending) { break; } } bw_History.ReportProgress(0, "Pre-selecting nearest positions finished, " + NearestPositions.Count.ToString() + " positions."); // return if no positions left over if (NearestPositions.Count == 0) { return; } int startindex = 0; // set timeline to first reported position time = NearestPositions[0].Time; while ((!bw_History.CancellationPending) && (time <= To)) { if (Crossings.Count % 1000 == 0) { bw_History.ReportProgress(0, "Calculating at " + time.ToString("yyyy-MM-dd HH:mm:ss") + ", " + Crossings.Count.ToString() + " crossings so far."); } // calculate from timestamp DateTime from = time.AddMinutes(-Properties.Settings.Default.Planes_Position_TTL); // fill plane position cache PlaneInfoCache ac = new PlaneInfoCache(); int i = startindex; startindex = -1; while ((!bw_History.CancellationPending) && (i < NearestPositions.Count)) { // update ap in cache if relevant if (NearestPositions[i].Time >= from) { // store first index as startindex for next iteration if (startindex == -1) { startindex = i; } lock (ac) { ac.InsertOrUpdateIfNewer(NearestPositions[i]); } } // stop if position is newer than current time if (NearestPositions[i].Time > time) { break; } i++; } List <PlaneInfo> allplanes = ac.GetAll(time, Properties.Settings.Default.Planes_Position_TTL); // get nearest planes List <PlaneInfo> nearestplanes = AircraftData.Database.GetNearestPlanes(time, PPath, allplanes, Properties.Settings.Default.Planes_Filter_Max_Circumcircle, Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance, Properties.Settings.Default.Planes_MaxAlt); if ((nearestplanes != null) && (nearestplanes.Count() > 0)) { // get all planes crossing the path foreach (PlaneInfo plane in nearestplanes) { if (plane.IntQRB <= Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance) { // check if level value is available SignalLevelDesignator ad = SignalData.Database.SignalLevelFind(plane.Time); if (ad != null) { plane.SignalStrength = ad.Level; } else { plane.SignalStrength = double.MinValue; } lock (Crossings) { if (!Properties.Settings.Default.Analysis_CrossingHistory_WithSignalLevel || (ad != null)) { Crossings.Add(plane); } } } bw_History.ReportProgress(0, "Calculating at " + time.ToString("yyyy-MM-dd HH:mm:ss") + ", " + Crossings.Count.ToString() + " crossings so far."); } } time = time.AddSeconds(Stepwidth); } bw_History.ReportProgress(100, "Calculation done."); }