// 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);
                }
            }
        }
Exemple #2
0
        public override void SunEarthAzEl(DateTime time, out double sunAzimuth, out double sunElevation, out double earthAzimuth, out double earthElevation)
        {
            //sunAzimuth = sunElevation = earthAzimuth = earthElevation = 0d;
            //return;

            var    et    = DateTimeToET(time);
            var    state = new double[6];
            double lt    = 0d;

            double[] pos = { 0d, 0d, 0d };

            CSpice.spkgeo_c(SunId, et, "MOON_ME", MoonId, state, ref lt);

            CSpice.spkcpo_c("SUN", et, "SITE_TOPO", "CENTER", "NONE", pos, "MOON", "MOON_ME", state, ref lt);
            //var d = Math.Sqrt(state[0] * state[0] + state[1] * state[1] + state[2] * state[2]);
            //Console.WriteLine(@"HERMITE: Sun= dist={3} vec=[{0},{1},{2}]", state[0], state[1], state[2], d);

            sunAzimuth = -Math.Atan2(state[1], state[0]);
            var flatd = Math.Sqrt(state[0] * state[0] + state[1] * state[1]);

            sunElevation = Math.Atan2(state[2], flatd);

            CSpice.spkcpo_c("EARTH", et, "SITE_TOPO", "CENTER", "NONE", pos, "MOON", "MOON_ME", state, ref lt);
            //d = Math.Sqrt(state[0] * state[0] + state[1] * state[1] + state[2] * state[2]);
            //Console.WriteLine(@"HERMITE: Earth= dist={3} vec=[{0},{1},{2}]", state[0], state[1], state[2], d);

            earthAzimuth   = -Math.Atan2(state[1], state[0]);
            flatd          = Math.Sqrt(state[0] * state[0] + state[1] * state[1]);
            earthElevation = Math.Atan2(state[2], flatd);
        }
Exemple #3
0
        private void ProjectPoint(double[] rectan, ref PointF p)
        {
            double r = 0, lat_rad = 0, lon_rad = 0;

            CSpice.reclat_c(rectan, ref r, ref lon_rad, ref lat_rad);
            InMemoryInt16Terrain.GetLineSample(lat_rad, lon_rad, out int line, out int sample);
            p.X = sample;
            p.Y = line;
        }
        unsafe void GeneratePSRImage()
        {
            var side = TerrainPatch.DefaultSize;

            // Prepare bitmap
            var width       = side * IdBounds.Width;
            var height      = side * IdBounds.Height;
            var sum_image   = new Int32[height, width];
            var time_image  = new Int32[height, width];
            var bitmap_rect = new Rectangle(0, 0, width, height);

            // Generate sun vectors
            var start_time  = new DateTime(2000, 1, 1);
            var stop_time   = new DateTime(2019, 1, 1);
            var time_step   = TimeSpan.FromHours(2);
            var sun_vectors = new List <Vector3d>();

            for (var time = start_time; time <= stop_time; time += time_step)
            {
                sun_vectors.Add(CSpice.SunPosition(time));
            }

            Console.WriteLine(sun_vectors.Count);

            System.Diagnostics.Debug.Assert(sun_vectors.Count <= 256 * 256 * 256);

            // Calculate psr image; parallelize over patches
            var options = new ParallelOptions {
                MaxDegreeOfParallelism = ViperEnvironment.MaxDegreeOfParallelism
            };                                                                                                       //TODO: Environment.ProcessorCount - 2 isn't working

            Parallel.ForEach(_patches, options,
                             patch =>
            {
                patch.FillPointsAndMatrices(ViperEnvironment.Terrain);
                var base_row = (patch.Id.Y - IdBounds.Top) * side;
                var base_col = (patch.Id.X - IdBounds.Left) * side;
                for (var row = 0; row < side; row++)
                {
                    var row1 = row + base_row;
                    for (var col = 0; col < side; col++)
                    {
                        var horizon = patch.Horizons[row][col];
                        var sum     = 0;
                        var time    = 0;
                        for (var svi = 0; svi < sun_vectors.Count; svi++)
                        {
                            var sun = sun_vectors[svi];
                            patch.GetAzEl(sun, col, row, out float sun_azimuth_rad, out float sun_elevation_rad);
                            var val = (int)(255f * horizon.SunFraction2(sun_azimuth_rad * 180f / 3.141592653589f, sun_elevation_rad * 180f / 3.141592653589f));
                            sum    += val;
                            time   += Math.Sign(val);
                        }
Exemple #5
0
        void FillAzimuthElevation()
        {
            var       center_patch = GetCenterPatch();
            var       center_pt    = center_patch.PointInPatch(new Point(TerrainPatch.DEM_size / 2, TerrainPatch.DEM_size / 2));
            var       mat          = center_patch.Matrices[center_pt.Y][center_pt.X];
            const int per_degree   = 4;
            const int count        = 360 * per_degree;
            var       slope_array  = Enumerable.Range(0, count).Select(i => float.MinValue).ToArray();
            var       vec_array    = new PointF[count];
            var       stop         = TileLightingProductManager.MetonicCycleStop;
            var       step         = TileLightingProductManager.MetonicCycleStep;
            var       temp         = new Vector3d();

            for (var time = TileLightingProductManager.MetonicCycleStart; time <= stop; time += step)
            {
                var sun = CSpice.SunPosition(time);
                TerrainPatch.Transform(ref sun, 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 = azimuth_rad * 180d / Math.PI;
                var index       = (int)(azimuth_deg * per_degree);
                var alen        = Math.Sqrt(sun_x * sun_x + sun_y * sun_y);
                var slope       = (float)(sun_z / alen);
                if (slope > slope_array[index])
                {
                    slope_array[index] = slope;
                    vec_array[index]   = new PointF((float)(sun_x / alen), (float)(sun_y / alen));
                }
            }
            var slope_list = new List <float>();
            var vec_list   = new List <PointF>();

            for (var i = 0; i < slope_array.Length; i++)
            {
                var s = slope_array[i];
                if (s > float.MinValue)
                {
                    slope_list.Add(s);
                    vec_list.Add(vec_array[i]);
                }
            }
            cpu_slope    = slope_array.ToArray();
            cpu_vector_x = vec_list.Select(p => p.X).ToArray();
            cpu_vector_y = vec_list.Select(p => p.Y).ToArray();
        }
Exemple #6
0
 public Vector3d EarthPosition(DateTime time)
 {
     lock (this)
     {
         var ticks = time.Ticks;
         var rep   = ticks - (ticks / _minimumStep);
         if (_earthCache.TryGetValue(rep, out Vector3d v))
         {
             return(v);
         }
         var    et = (rep - _epoch) / 10000000L + 3d;
         double lt = 0d;
         CSpice.spkgeo_c(EarthId, et, "MOON_ME", MoonId, _state, ref lt);
         v = new Vector3d(_state[0], _state[1], _state[2]);
         if (_earthCache.Count < MaxCacheCount)
         {
             _earthCache.Add(rep, v);
         }
         return(v);
     }
 }
        void PrepareSlopeArray(DateTime start, DateTime stop, TimeSpan step)
        {
            const int bins = 4 * 360;
            var       flip = -LonFactor;

            for (var i = 0; i < bins; i++)
            {
                cpu_slope[i] = float.MaxValue;
            }

            var elev = cpu_slope;

            for (var time = start; time <= stop; time += step)
            {
                var vec           = CSpice.SunPosition(time);
                var x             = vec[0];
                var y             = vec[1];
                var z             = vec[2];
                var alen          = Math.Sqrt(x * x + y * y);
                var azimuth_rad   = (float)(Math.Atan2(y, x) + Math.PI); // [0,2PI]
                var azimuth_index = (int)((azimuth_rad / (2 * Math.PI)) * bins);
                var slope         = flip * z / alen;
                if (slope < elev[azimuth_index])
                {
                    elev[azimuth_index] = (float)slope;
                }
            }

            if (false)
            {
                for (var i = 0; i < elev.Length; i++)
                {
                    elev[i] = 0f;
                }
            }
        }
Exemple #8
0
 public static void Furnish(string path)
 {
     Console.WriteLine(@"Spice furnishing {0}", path);
     CSpice.furnsh_c(path);
 }
Exemple #9
0
        public override void DSNAzEl(DateTime time, double lat, double lon, double height, out double dsnaz, out double dsnel)
        {
            const double stationHorizonMask = 10d * Math.PI / 190d;

            var siteLat = lat * Math.PI / 180d;
            var siteLon = lon * Math.PI / 180d;

            double[] traverseSite = { 0d, 0d, 0d };
            CSpice.pgrrec_c("MOON", siteLon, siteLat, 0d, MoonRadius, 0f, traverseSite);

            var pz   = MoonRadius * Math.Sin(siteLat);
            var temp = MoonRadius * Math.Cos(siteLat);
            var px   = temp * Math.Cos(siteLon);
            var py   = temp * Math.Sin(siteLon);

            Debug.Assert(Math.Abs(px - traverseSite[0]) < 1d);
            Debug.Assert(Math.Abs(py - traverseSite[1]) < 1d);
            Debug.Assert(Math.Abs(pz - traverseSite[2]) < 1d);

            var    et         = DateTimeToET(time);
            var    state      = new double[6];
            var    earthState = new double[6];
            var    moonPositionFromStation = new double[3];
            double lt = 0d;

            CSpice.spkcpo_c("EARTH", et, "SITE_TOPO", "CENTER", "NONE", traverseSite, "MOON", "MOON_ME", earthState, ref lt);
            var earthAzimuth   = -Math.Atan2(earthState[1], earthState[0]);
            var flatd1         = Math.Sqrt(earthState[0] * earthState[0] + earthState[1] * earthState[1]);
            var earthElevation = Math.Atan2(earthState[2], flatd1);

            var data = new List <DSNSiteData>();

            for (var i = 0; i < DSNSiteNames.Length; i++)
            {
                // Station to the traverse site
                CSpice.spkezp_c(MoonId, et, DSNSiteFrames[i], "NONE", DSNIds[i], moonPositionFromStation, ref lt);
                var moonElevation = Math.Atan2(moonPositionFromStation[2], Math.Sqrt(moonPositionFromStation[0] * moonPositionFromStation[0] + moonPositionFromStation[1] * moonPositionFromStation[1]));

                // Traverse site to the station
                CSpice.spkcpo_c(DSNSiteNames[i], et, "SITE_TOPO", "CENTER", "NONE", traverseSite, "MOON", "MOON_ME", state, ref lt);

                var flatd = Math.Sqrt(state[0] * state[0] + state[1] * state[1]);
                data.Add(new DSNSiteData
                {
                    SiteToStationAzimuth   = -Math.Atan2(state[1], state[0]),
                    SiteToStationElevation = Math.Atan2(state[2], flatd),
                    StationToMoonElevation = moonElevation,
                    Site = DSNSiteNames[i]
                });
            }

            foreach (var d in data)
            {
                Console.WriteLine("complex={0} elev@complex={1}  complexElev@traverse={2} complexAz@traverse={3}", d.Site, d.StationToMoonElevation, d.SiteToStationElevation, d.SiteToStationAzimuth);
            }

            DSNSiteData  bestData    = null;
            const double highestElev = double.MinValue;

            foreach (var d in data)
            {
                if (d.StationToMoonElevation >= stationHorizonMask && d.SiteToStationElevation > highestElev)
                {
                    bestData = d;
                }
            }

            if (bestData == null)
            {
                Console.WriteLine(@"Couldn't find a suitable ground complex.  Using {0}", data[0].Site);
                bestData = data[0];
            }
            dsnaz = bestData.SiteToStationAzimuth;
            dsnel = bestData.SiteToStationElevation;

            Console.WriteLine(@"moon center");
            Console.WriteLine(@"  earth az={0}", earthAzimuth);
            Console.WriteLine(@"  earth el={0}", earthElevation);
            Console.WriteLine(@"To {0}", bestData.Site);
            Console.WriteLine(@"  earth az={0}", bestData.SiteToStationAzimuth);
            Console.WriteLine(@"  earth el={0}", bestData.SiteToStationElevation);
        }
        public void WriteSafeHavenGeotiffs(string path)
        {
            var outer_start = Start.AddDays(-28);
            var outer_stop  = Stop.AddDays(28);

            GetLowEarthTimes(outer_start, outer_stop, out List <DateTime> times_start_to_stop, out List <int> indices_of_minima_earth_elevation);

            for (var i = 0; i < indices_of_minima_earth_elevation.Count; i++)
            {
                Console.WriteLine($"i={i} index={indices_of_minima_earth_elevation[i]} time={times_start_to_stop[indices_of_minima_earth_elevation[i]]}");
            }
            var region_width  = Region.Width;
            var region_height = Region.Height;

            var combined     = new float[region_height, region_width];
            var month_images = Enumerable.Range(0, indices_of_minima_earth_elevation.Count).Select(i => new float[region_height, region_width]).ToList();

            var sun_vectors   = times_start_to_stop.Select(time => CSpice.SunPosition(time)).ToList();
            var earth_vectors = times_start_to_stop.Select(time => CSpice.EarthPosition(time)).ToList();

            // Get the indexes in the time and vector arrays of Start and Stop
            var first_inside = times_start_to_stop.Select((time, index) => (time, index)).Where(pair => pair.time >= Start).Select(pair => pair.index).First();
            var last_inside  = -1;

            for (var i = times_start_to_stop.Count - 1; i >= 0; i--)
            {
                if (times_start_to_stop[i] <= Stop)
                {
                    last_inside = i;
                    break;
                }
            }

            //var debugpt = new Point(Region.Left + 545, Region.Top + 490);
            //debugpt = new Point(Region.Left + 494, Region.Top + 438);
            var ids = TerrainPatch.EnumerateIds(TerrainPatch.CoveringIdRectangle(Region)).ToList();

            {
                var not_generated = ids.Where(id => !File.Exists(TerrainPatch.FromId(id, ObserverHeightInMeters).Path)).ToList();
                Console.WriteLine($"{not_generated.Count} patches haven't been generated yet.  Generating them.");
                var gpuProcessor = ViperEnvironment.Processor as CPUHorizons;
                var queue        = not_generated.Select(id => TerrainPatch.FromId(id)).ToList();
                gpuProcessor.RunQueue(queue, writeHorizons: WriteHorizons, unloadHorizons: true);
            }

            Parallel.ForEach(ids,
                             new ParallelOptions {
                MaxDegreeOfParallelism = ViperEnvironment.MaxDegreeOfParallelism
            },
                             id =>
            {
                var patch = GetPatchWithHorizons(id, ObserverHeightInMeters);
                for (var row = 0; row < TerrainPatch.DefaultSize; row++)
                {
                    var region_row = (patch.Line + row) - Region.Y;
                    if (region_row < 0 || region_row >= region_height)
                    {
                        continue;
                    }
                    for (var col = 0; col < TerrainPatch.DefaultSize; col++)
                    {
                        //if ((patch.Line + row) != debugpt.Y || (patch.Sample + col) != debugpt.X)
                        //    continue;
                        var region_col = patch.Sample + col - Region.X;
                        if (region_col < 0 || region_col >= region_width)
                        {
                            continue;
                        }
                        var has_sun     = patch.GetLightCurve(row, col, sun_vectors).Select(sun => sun >= SafeHavenSunThreshold).ToList();
                        var has_comm    = patch.GetEarthOverHorizonCurve(row, col, earth_vectors).Select(rise => rise >= EarthMultipathThreshold).ToList();
                        var month_steps = MaxShadowWithoutComm2(indices_of_minima_earth_elevation, has_sun, has_comm);
                        combined[region_row, region_col] = 2f * month_steps.Max();
                        for (var i = 0; i < month_steps.Count; i++)
                        {
                            month_images[i][region_row, region_col] = 2f * month_steps[i];
                        }
                    }
                }
            });

            {
                var path_combined = LandingSiteDataset.AppendToFilename(path, "_combined");
                GeotiffHelper.WriteArrayAsGeotiff(combined, Region, path_combined);
                WriteSafeHavenOverlay(combined, path_combined);
            }

            for (var i = 0; i < month_images.Count; i++)
            {
                var time  = times_start_to_stop[indices_of_minima_earth_elevation[i]];
                var path1 = LandingSiteDataset.AppendToFilename(path, "_" + time.ToString("yyyy-MM-dd"));
                GeotiffHelper.WriteArrayAsGeotiff(month_images[i], Region, path1);
                WriteSafeHavenOverlay(month_images[i], path1);
            }
        }