/// <inheritdoc /> protected bool Equals(SatelliteVisibilityPeriod other) { return(Satellite.Equals(other.Satellite) && Start.Equals(other.Start) && End.Equals(other.End) && MaxElevation.Equals(other.MaxElevation) && MaxElevationTime.Equals(other.MaxElevationTime) && ReferencePosition.Equals(other.ReferencePosition)); }
/// <summary> /// Creates a list of all of the predicted observations within the specified time period for this GroundStation. /// </summary> /// <param name="satellite">The satellite to observe</param> /// <param name="start">The time to start observing</param> /// <param name="end">The time to end observing</param> /// <param name="deltaTime">The time step for the prediction simulation</param> /// <param name="minElevation">The minimum elevation. Default is Angle.Zero.</param> /// <param name="clipToStartTime">Whether to clip the start time of the first satellite visibility period to start, if applicable. Default is true</param> /// <param name="clipToEndTime">Whether to clip the end time of the last satellite visibility period to end, if applicable. Default is false</param> /// <param name="resolution">The number of second decimal places to calculate for the start and end times. Cannot be greater than 7 (i.e. greater than tick resolution). Default is 3.</param> /// <returns>A list of observations where an AOS is seen at or after the start parameter</returns> /// <exception cref="ArgumentException">Thrown if start is greater than or equal to end, deltaTime is non-positive, resolution is not in range 0-7, or minElevation is greater than 90°</exception> public List <SatelliteVisibilityPeriod> Observe( Satellite satellite, DateTime start, DateTime end, TimeSpan deltaTime, Angle minElevation = default(Angle), // default is Angle.Zero bool clipToStartTime = true, // default is true as it is assumed typical use case will be for future propagation, not searching into the past bool clipToEndTime = false, // default is false as it is assumed typical use case will be to capture entire future pass int resolution = 3) { // check input constraints if (deltaTime.TotalSeconds <= 0) { throw new ArgumentException("deltaTime must be positive", "deltaTime"); } start = start.ToStrictUtc(); end = end.ToStrictUtc(); if (start >= end) { throw new ArgumentException("start time must be less than end time", "start"); } if (deltaTime <= TimeSpan.Zero) { throw new ArgumentException("deltaTime must be greater than zero", "deltaTime"); } if (resolution < 0) { throw new ArgumentException("resolution must be non-negative", "resolution"); } if (resolution > 7) { throw new ArgumentException("resolution must be no more than 7 decimal places (no more than tick resolution)", "resolution"); } if (minElevation != null && minElevation.Degrees > 90) { throw new ArgumentException("minElevation cannot be greater than 90°", "minElevation"); } start = start.Round(deltaTime); var clippedEnd = clipToEndTime ? (DateTime?)end : null; var obs = new List <SatelliteVisibilityPeriod>(); DateTime aosTime; var t = start; do { // find the AOS Time of the next pass aosTime = FindNextBelowToAboveCrossingPoint(satellite, t, end, deltaTime, minElevation, resolution); if (aosTime > end) { break; } // if aosTime is greater than end, we're done t = aosTime + deltaTime; // find the LOS time and max elevation for the next pass DateTime losTime; DateTime maxElTime; if (clippedEnd.HasValue && t > clippedEnd.Value) { losTime = clippedEnd.Value; maxElTime = clippedEnd.Value; } else { var tu = FindNextAboveToBelowCrossingPoint(satellite, t, deltaTime, minElevation, resolution, clippedEnd); losTime = tu.CrossingPointTime; maxElTime = tu.MaxElevationTime; } var before = maxElTime - deltaTime; if (clipToStartTime) // ensure before is clipped for max elevation search { before = start > before ? start : before; } var after = maxElTime + deltaTime; if (clipToEndTime) // ensure after is clipped for max elevation search { after = end < after ? end : after; } // add the visibility period for the pass var refinedMaxElResult = FindMaxElevation(satellite, before, maxElTime, after, resolution); var maxEl = refinedMaxElResult.Item1; maxElTime = refinedMaxElResult.Item2; obs.Add(new SatelliteVisibilityPeriod(satellite, aosTime, losTime, maxEl, maxElTime, Location)); t = losTime + deltaTime; } while (t <= end); // if clipToStartTime is false and the start time has been clipped, walk back in time until previous AOS crossing point has been found if (!clipToStartTime && obs.Count > 0 && obs[0].Start == start) { var first = obs[0]; var tu = FindNextAboveToBelowCrossingPoint(satellite, first.Start, deltaTime.Negate(), minElevation, resolution); var maxElTime = first.MaxElevation > tu.MaxElevation ? first.MaxElevationTime : tu.MaxElevationTime; var refinedMaxElResult = FindMaxElevation(satellite, maxElTime - deltaTime, maxElTime, maxElTime + deltaTime, resolution); var maxEl = refinedMaxElResult.Item1; maxElTime = refinedMaxElResult.Item2; obs[0] = new SatelliteVisibilityPeriod(satellite, tu.CrossingPointTime, first.End, maxEl, maxElTime, first.ReferencePosition); } return(obs); }
/// <inheritdoc /> protected bool Equals(SatelliteVisibilityPeriod other) { return(Satellite.Equals(other.Satellite) && Start.Equals(other.Start) && End.Equals(other.End) && MaxElevation.Equals(other.MaxElevation) && StartAzimuth.Equals(other.StartAzimuth) && EndAzimuth.Equals(other.EndAzimuth)); }