示例#1
0
        public double[] Interpolate(double jdtdb, EphemerisComponent target, EphemerisComponent center = EphemerisComponent.SolarSystemBarycenter)
        {
            if (jdtdb < StartEpoch || jdtdb > FinalEpoch)
            {
                throw new ArgumentOutOfRangeException(nameof(jdtdb), TimeOutOfRange);
            }

            var targetCoordinates = new double[6];
            var centerCoordinates = new double[6];

            // Nutation, Libration, Angular Velocity and TT-TDB.
            if (target == EphemerisComponent.EarthNutation || target == EphemerisComponent.MoonLibration ||
                target == EphemerisComponent.MoonAngularVelocity || target == EphemerisComponent.TTMinusTDB)
            {
                return(InterpolateChebyshev(jdtdb, target));
            }

            // Moon at Earth Geocenter.
            if (target == EphemerisComponent.Moon && center == EphemerisComponent.Earth)
            {
                targetCoordinates = InterpolateChebyshev(jdtdb, target);
            }

            // Earth at Moon Geocenter.
            else if (target == EphemerisComponent.Earth && center == EphemerisComponent.Moon)
            {
                targetCoordinates = InterpolateChebyshev(jdtdb, center);
                for (var axis = 0; axis < targetCoordinates.Length; axis++)
                {
                    targetCoordinates[axis] = -targetCoordinates[axis];
                }
            }

            // Anything that relates to either Earth or Moon.
            else if (target == EphemerisComponent.Earth || target == EphemerisComponent.Moon ||
                     center == EphemerisComponent.Earth || center == EphemerisComponent.Moon)
            {
                var emrat = 1.0 / (1.0 + constants["EMRAT"]);
                if (target == EphemerisComponent.Moon || center == EphemerisComponent.Moon)
                {
                    emrat -= 1.0;
                }

                var embCoordinates  = InterpolateChebyshev(jdtdb, EphemerisComponent.EarthMoonBarycenter);
                var moonCoordinates = InterpolateChebyshev(jdtdb, EphemerisComponent.Moon);

                // Earth/Moon at Planetocenter/SSB.
                if (target == EphemerisComponent.Earth || target == EphemerisComponent.Moon)
                {
                    if (center != EphemerisComponent.SolarSystemBarycenter)
                    {
                        targetCoordinates = InterpolateChebyshev(jdtdb, center);
                    }
                    for (var axis = 0; axis < targetCoordinates.Length; axis++)
                    {
                        targetCoordinates[axis] = (embCoordinates[axis] - emrat * moonCoordinates[axis]) - targetCoordinates[axis];
                    }
                }

                // Planet/SSB at Earth/Moon Geocenter.
                else
                {
                    if (target != EphemerisComponent.SolarSystemBarycenter)
                    {
                        targetCoordinates = InterpolateChebyshev(jdtdb, target);
                    }
                    for (var axis = 0; axis < targetCoordinates.Length; axis++)
                    {
                        targetCoordinates[axis] = targetCoordinates[axis] - (embCoordinates[axis] - emrat * moonCoordinates[axis]);
                    }
                }
            }

            // Anything that relates to bodies other than Earth/Moon.
            else
            {
                if (target != EphemerisComponent.SolarSystemBarycenter)
                {
                    targetCoordinates = InterpolateChebyshev(jdtdb, target);
                }
                if (center != EphemerisComponent.SolarSystemBarycenter)
                {
                    centerCoordinates = InterpolateChebyshev(jdtdb, center);
                }
                for (var axis = 0; axis < targetCoordinates.Length; axis++)
                {
                    targetCoordinates[axis] -= centerCoordinates[axis];
                }
            }

            for (var axis = 0; axis < targetCoordinates.Length; axis++)
            {
                targetCoordinates[axis] /= constants["AU"];
            }

            return(targetCoordinates);
        }
示例#2
0
        private double[] InterpolateChebyshev(double tdb, EphemerisComponent component)
        {
            if (!pointers.ContainsKey(component) || pointers[component].CoefficientSetCount == 0)
            {
                throw new ArgumentException(EphemerisComponentNotAvailable, nameof(component));
            }

            var recordPointer = pointers[component];
            var interval      = (tdb - StartEpoch) / recordSpan;
            var segment       = (int)Math.Floor(interval);

            // Use previous segment if time is final epoch.
            if (Math.Abs(tdb - FinalEpoch) < double.Epsilon)
            {
                segment--;
            }

            var subInterval = (interval - segment) * recordPointer.CoefficientSetCount;
            var subSegment  = (int)Math.Floor(subInterval);
            var timeSegment = 2.0 * (subInterval - subSegment) - 1.0;

            // Load segment if not already loaded.
            if (isFirstReading || tdb < coefficients[0] || tdb >= coefficients[1])
            {
                reader.BaseStream.Seek(dataOffset + segment * coefficients.Length * sizeof(double), SeekOrigin.Begin);
                for (var i = 0; i < coefficients.Length; i++)
                {
                    coefficients[i] = reader.ReadDouble();
                }

                isFirstReading = false;
            }

            // Default is set to cartesian axes count.
            var coordinateCount = 3;

            if (component == EphemerisComponent.EarthNutation)
            {
                coordinateCount = 2;
            }
            else if (component == EphemerisComponent.TTMinusTDB)
            {
                coordinateCount = 1;
            }

            var coordinates = new double[coordinateCount * 2];

            for (var axis = 0; axis < coordinateCount; axis++)
            {
                var p0     = 1.0;
                var p1     = timeSegment;
                var p2     = 0.0;
                var v0     = 0.0;
                var v1     = 1.0;
                var v2     = 0.0;
                var offset = recordPointer.CoefficientCountPerSet * (coordinateCount * subSegment + axis) + recordPointer.Offset;

                coordinates[axis] = coefficients[offset];
                for (var i = 1; i < recordPointer.CoefficientCountPerSet; i++)
                {
                    coordinates[axis] += coefficients[offset + i] * p1;
                    coordinates[axis + coordinateCount] += coefficients[offset + i] * v1;

                    p2 = 2.0 * timeSegment * p1 - p0;
                    v2 = 2.0 * timeSegment * v1 - v0 + 2 * p1;
                    p0 = p1;
                    p1 = p2;
                    v0 = v1;
                    v1 = v2;
                }
                coordinates[axis + coordinateCount] *= (2 * recordPointer.CoefficientSetCount) / recordSpan;
            }

            return(coordinates);
        }