/// <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);
        }
Exemplo n.º 2
0
 public static SunVectorCache GetSingleton() => _singleton != null ? _singleton : _singleton = new SunVectorCache();