public void ProjectionKauai()
        {
            var definition = SatelliteRegistry.Locate(Goes17DefinitionPrefix);

            Assert.NotNull(definition, "Unable to find satellite definition");

            var imageOffset = Constants.Satellite.Offset.TwoKm;

            const int x = 1614;
            const int y = 1564;

            // Convert from scanning angle to geodetic
            var scanningX = imageOffset.ToHorizontalScanningAngle(x);
            var scanningY = imageOffset.ToVerticalScanningAngle(y);

            ReverseGeostationaryProjection.ToLatitudeLongitude(scanningX, scanningY, definition.Longitude, definition.Height, out var latitude, out var longitude);

            FromRadians(latitude).Degrees.Should().BeApproximately(21.869911403254573, Precision);
            FromRadians(longitude).Degrees.Should().BeApproximately(-159.66206692006023, Precision);

            // Convert back to scanning angle
            GeostationaryProjection.ToScanningAngle(latitude, longitude, definition, out var scanningXResult, out var scanningYResult);
            scanningXResult.Should().BeApproximately(scanningX, Precision);
            scanningYResult.Should().BeApproximately(scanningY, Precision);

            imageOffset.ToImageCoordinates(scanningXResult, scanningYResult, out var targetX, out var targetY);

            Math.Round(targetX).Should().BeApproximately(x, PixelPrecision);
            Math.Round(targetY).Should().BeApproximately(y, PixelPrecision);
        }
        public void ProjectionLakeTaupo()
        {
            var definition = SatelliteRegistry.Locate(Goes17DefinitionPrefix);

            Assert.NotNull(definition, "Unable to find satellite definition");

            var imageOffset = Constants.Satellite.Offset.TwoKm;

            const int x = 1050;
            const int y = 4533;

            // Convert from scanning angle to geodetic
            var scanningX = imageOffset.ToHorizontalScanningAngle(x);
            var scanningY = imageOffset.ToVerticalScanningAngle(y);

            ReverseGeostationaryProjection.ToLatitudeLongitude(scanningX, scanningY, definition.Longitude, definition.Height, out var latitude, out var longitude);

            FromRadians(latitude).Degrees.Should().BeApproximately(-38.70625734950147, Precision);
            FromRadians(longitude).Degrees.Should().BeApproximately(175.9626023681634, Precision);

            // Convert back to scanning angle
            GeostationaryProjection.ToScanningAngle(latitude, longitude, definition, out var scanningXResult, out var scanningYResult);
            scanningXResult.Should().BeApproximately(scanningX, Precision);
            scanningYResult.Should().BeApproximately(scanningY, Precision);

            imageOffset.ToImageCoordinates(scanningXResult, scanningYResult, out var targetX, out var targetY);

            Math.Round(targetX).Should().BeApproximately(x, PixelPrecision);
            Math.Round(targetY).Should().BeApproximately(y, PixelPrecision);
        }
        public void ProjectionCalifornia()
        {
            var definition = SatelliteRegistry.Locate(Goes17DefinitionPrefix);

            Assert.NotNull(definition, "Unable to find satellite definition");

            var imageOffset = Constants.Satellite.Offset.TwoKm;

            const int x = 3717;
            const int y = 1275;

            // Convert from scanning angle to geodetic
            var scanningX = imageOffset.ToHorizontalScanningAngle(x);
            var scanningY = imageOffset.ToVerticalScanningAngle(y);

            ReverseGeostationaryProjection.ToLatitudeLongitude(scanningX, scanningY, definition.Longitude, definition.Height, out var latitude, out var longitude);

            FromRadians(latitude).Degrees.Should().BeApproximately(28.007393788242464, Precision);
            FromRadians(longitude).Degrees.Should().BeApproximately(-115.44783176403854, Precision);

            // Convert back to scanning angle
            GeostationaryProjection.ToScanningAngle(latitude, longitude, definition, out var scanningXResult, out var scanningYResult);
            scanningXResult.Should().BeApproximately(scanningX, Precision);
            scanningYResult.Should().BeApproximately(scanningY, Precision);

            imageOffset.ToImageCoordinates(scanningXResult, scanningYResult, out var targetX, out var targetY);

            Math.Round(targetX).Should().BeApproximately(x, PixelPrecision);
            Math.Round(targetY).Should().BeApproximately(y, PixelPrecision);
        }
        public void ProjectionFernandinaIsland()
        {
            var definition = SatelliteRegistry.Locate(Goes17DefinitionPrefix);

            Assert.NotNull(definition, "Unable to find satellite definition");

            var imageOffset = Constants.Satellite.Offset.TwoKm;

            const int x = 4866;
            const int y = 2735;

            // Convert from scanning angle to geodetic
            var scanningX = imageOffset.ToHorizontalScanningAngle(x);
            var scanningY = imageOffset.ToVerticalScanningAngle(y);

            ReverseGeostationaryProjection.ToLatitudeLongitude(scanningX, scanningY, definition.Longitude, definition.Height, out var latitude, out var longitude);

            FromRadians(latitude).Degrees.Should().BeApproximately(-0.4489090116682934, Precision);
            FromRadians(longitude).Degrees.Should().BeApproximately(-91.39243691622593, Precision);
        }
        public void Invoke(int y)
        {
            var span      = _target.GetPixelRowSpan(y);
            var scanningY = _options.ImageOffset !.ToVerticalScanningAngle(y);

            var verticalScanningCalculations = ReverseGeostationaryProjection.VerticalScanningCalculations(scanningY, _satelliteHeight);

            for (var x = 0; x < span.Length; x++)
            {
                var scanningX = _options.ImageOffset.ToHorizontalScanningAngle(x);
                ReverseGeostationaryProjection.ToLatitudeLongitude(scanningX, verticalScanningCalculations, _satelliteLongitude, out var latitude, out var longitude);

                if (double.IsNaN(longitude) || double.IsNaN(latitude))
                {
                    span[x] = Color.Transparent;
                    continue;
                }

                var x1 = longitude.ScaleToWidthD(_sourceWidth).Limit(0, _sourceWidth);
                var y1 = latitude.ScaleToHeightD(_sourceHeight);

                span[x] = _sourceBuffer.GetInterpolatedPixel(x1, y1, _options.InterpolationType);
            }
        }