// Return all times from start to stop. Also return the indexes of the times at which the earth elevation reaches a minima void GetLowEarthTimes(DateTime outer_start, DateTime outer_stop, out List <DateTime> all_times, out List <int> indices_of_minima_earth_elevation) { var center = new Point(Region.Left + Region.Width / 2, Region.Top + Region.Height / 2); var centerPatch = ViperEnvironment.GetPatch(TerrainPatch.LineSampleToId(center)); centerPatch.FillMatrices(ViperEnvironment.Terrain); // Generate the time / elevation pairs all_times = new List <DateTime>(); for (var time = outer_start; time <= outer_stop; time += Step) { all_times.Add(time); } var earth_elevations = all_times.Select(t => { centerPatch.GetAzEl(CSpice.EarthPosition(t), 0, 0, out float _, out float earth_elevation_rad); return(earth_elevation_rad); }).ToList(); // Find minima indices_of_minima_earth_elevation = new List <int>(); for (var i = 1; i < earth_elevations.Count - 1; i++) { if (Start <= all_times[i] && all_times[i] <= Stop && earth_elevations[i - 1] > earth_elevations[i] && earth_elevations[i] < earth_elevations[i + 1]) { indices_of_minima_earth_elevation.Add(i); } } }
/// <summary> /// Map over the fraction of the sun's disk visible times Cos(theta) - theta is the angle between the sun and normal /// </summary> /// <param name="line"></param> /// <param name="sample"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <param name="step"></param> /// <param name="action"></param> /// <returns></returns> public bool MapOverSunContribution(int line, int sample, DateTime start, DateTime stop, TimeSpan step, Action <DateTime, float> action) { var id = TerrainPatch.LineSampleToId(line, sample); var patch = GetPatch(id); if (patch == null) { return(false); } var cross = GetSurfaceNormal(line, sample); var y_offset = line - patch.Line; var x_offset = sample - patch.Sample; var mat = patch.Matrices[y_offset][x_offset]; var horizon = patch.Horizons[y_offset][x_offset]; if (!horizon.IsDegrees) { lock (horizon) horizon.ConvertSlopeToDegrees(); } var cache = SunVectorCache.GetSingleton(); var temp = new Vector3d(); for (var time = start; time <= stop; time += step) { var sunvec = cache.SunPosition(time); TerrainPatch.Transform(ref sunvec, ref mat, ref temp); var sun_x = temp[0]; var sun_y = temp[1]; var sun_z = temp[2]; var azimuth_rad = Math.Atan2(sun_y, sun_x) + Math.PI; // [0,2PI] var azimuth_deg = (float)(azimuth_rad * 180d / Math.PI); var alen = Math.Sqrt(sun_x * sun_x + sun_y * sun_y); var slope = sun_z / alen; var elevation_deg = ((float)Math.Atan(slope)) * 180f / 3.141592653589f; var sunfrac = horizon.SunFraction2(azimuth_deg, elevation_deg); //if (line == 17522 && sample == 12388) //{ // Console.WriteLine($"{line},{sample}, time={time} elevation_deg={elevation_deg} sun={sunfrac}"); //} sunvec.NormalizeFast(); // Normalize before calculating surface temp var dot = Vector3d.Dot(sunvec, cross); var sun_contrib = dot < 0d ? 0d : sunfrac * dot; //if (sun_contrib > 0) // Console.WriteLine(sun_contrib); action(time, (float)sun_contrib); } return(true); }
public void MapOverLightCurve(int line, int sample, DateTime start, DateTime stop, TimeSpan step, Action <DateTime, float> action) { var id = TerrainPatch.LineSampleToId(line, sample); var patch = GetPatch(id); if (patch == null) { return; } var y_offset = line - patch.Line; var x_offset = sample - patch.Sample; var mat = patch.Matrices[y_offset][x_offset]; var horizon = patch.Horizons[y_offset][x_offset]; if (!horizon.IsDegrees) { lock (horizon) horizon.ConvertSlopeToDegrees(); } var cache = SunVectorCache.GetSingleton(); var temp = new Vector3d(); for (var time = start; time <= stop; time += step) { var sunvec = cache.SunPosition(time); TerrainPatch.Transform(ref sunvec, ref mat, ref temp); var sun_x = temp[0]; var sun_y = temp[1]; var sun_z = temp[2]; var azimuth_rad = Math.Atan2(sun_y, sun_x) + Math.PI; // [0,2PI] var azimuth_deg = (float)(azimuth_rad * 180d / Math.PI); var alen = Math.Sqrt(sun_x * sun_x + sun_y * sun_y); var slope = sun_z / alen; var elevation_deg = ((float)Math.Atan(slope)) * 180f / 3.141592653589f; var sun = horizon.SunFraction2(azimuth_deg, elevation_deg); //Console.WriteLine($"time={time} elevation_deg={elevation_deg} sun={sun}"); action(time, sun); } }
private void UpdateSunCache() { lock (_horizonCache) { var keys = _sunCache.Keys.ToList(); foreach (var probe in keys) { var pt = new Point((int)probe.Location.X, (int)probe.Location.Y); var id = TerrainPatch.LineSampleToId(pt); if (!LunarHorizon.Singleton.PatchCache.TryGetValue(id, out TerrainPatch patch)) { continue; } var ptInPatch = patch.PointInPatch(pt); _sunCache[probe] = GetSunCurve(patch, ptInPatch, LunarHorizon.Singleton.MapView.SunVector, probe.Color); } } UpdatePlots(); }
// Cache by id private bool HorizonsHaveBeenCalculated(ConsolidatedLine consolidated) { var pixel = consolidated.Pixel; var id = TerrainPatch.LineSampleToId(pixel.Y, pixel.X); lock (_precache) { if (_precache.TryGetValue(id, out bool hasHorizons)) { return(hasHorizons); } var patch = TerrainPatch.FromId(id); var horizons_path = patch.Path; var result = File.Exists(horizons_path); if (result) { _cache.Add(id, patch); } _precache.Add(id, result); return(result); } }
private Point?GetRequestedId(LocationProbe probe) { var pt = GetRequest(probe); return(pt.HasValue ? (Point?)TerrainPatch.LineSampleToId(pt.Value) : null); }