private CurveItem GetSunCurve(TerrainPatch patch, Point pt, math.Vector3d sun, Color color)
        {
            patch.FillPointsAndMatrices(LunarHorizon.Terrain);
            patch.GetAzEl(sun, pt.X, pt.Y, out float az_rad, out float el_rad);

            {
                var horizon = patch.GetHorizon(pt.Y, pt.X);
                var frac    = (byte)(255f * horizon.SunFraction2(az_rad * 180f / 3.141592653589f, el_rad * 180f / 3.141592653589f));
                Console.WriteLine($"patch.id={patch.Id} pt=[{pt.X},{pt.Y}] Sun frac={frac}");
            }

            var          az_deg = az_rad * 180f / 3.141592565589f;
            var          el_deg = el_rad * 180f / 3.141592565589f;
            const int    count  = 12;
            const double radius = 32d / 60d;
            var          points = new PointPairList();

            for (var i = 0; i <= count; i++)
            {
                var ang = i * 2d * Math.PI / count;
                points.Add(az_deg + radius * Math.Cos(ang), el_deg + radius * Math.Sin(ang));
            }
            return(new LineItem(null, points, color, SymbolType.None));
        }
        Bitmap GetHorizonDelta()
        {
            if (patch2 == null || patch1 == null)
            {
                return(null);
            }
            var width  = TerrainPatch.DefaultSize;
            var height = TerrainPatch.DefaultSize;

            if (imageDelta != null && (imageDelta.Width != width || imageDelta.Height != height))
            {
                imageDelta.Dispose();
                imageDelta = null;
            }
            if (imageDelta == null)
            {
                imageDelta = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
                var p = imageDelta.Palette;
                for (var i = 0; i < 255; i++)
                {
                    p.Entries[i] = Color.FromArgb(i, i, i);
                }
                imageDelta.Palette = p;
            }
            var bmp3 = imageDelta;

            var diffs = new List <float>();

            for (var row = 0; row < height; row++)
            {
                for (var col = 0; col < width; col++)
                {
                    diffs.Add(HorizonDifference(patch1.GetHorizon(row, col), patch2.GetHorizon(row, col)));
                }
            }
            var max = diffs.Max();

            //max = 0.01f;
            max = max * (tbSelectTime.Value / (float)(tbSelectTime.Maximum - tbSelectTime.Minimum));

            Console.WriteLine($"diffs[0]={diffs[0]} max={max}");

            var rect     = new Rectangle(0, 0, width, height);
            var bmp3data = bmp3.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp3.PixelFormat);

            unsafe
            {
                var ptr = 0;
                for (var row = 0; row < height; row++)
                {
                    var bmp3ptr = (byte *)bmp3data.Scan0 + bmp3data.Stride * row;
                    for (var col = 0; col < width; col++)
                    {
                        bmp3ptr[col] = (byte)(Math.Min(255f, 255f * diffs[ptr++] / max));
                    }
                }
            }
            bmp3.UnlockBits(bmp3data);

            //lbMaxDelta.Text = Math.Round(max).ToString();
            lbMaxDelta.Text = max.ToString();

            return(bmp3);
        }