// 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);
        }
Ejemplo n.º 3
0
        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);
        }