Пример #1
0
        /**
         * Constructor for a geodesic line staring at latitude <i>lat1</i>, longitude
         * <i>lon1</i>, and azimuth <i>azi1</i> (all in degrees) with a subset of the
         * capabilities included.
         * <p>
         * @param g A {@link Geodesic} object used to compute the necessary
         *   information about the GeodesicLine.
         * @param lat1 latitude of point 1 (degrees).
         * @param lon1 longitude of point 1 (degrees).
         * @param azi1 azimuth at point 1 (degrees).
         * @param caps bitor'ed combination of {@link GeodesicMask} values
         *   specifying the capabilities the GeodesicLine object should possess,
         *   i.e., which quantities can be returned in calls to {@link #Position
         *   Position}.
         * <p>
         * The {@link GeodesicMask} values are
         * <ul>
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#LATITUDE} for the latitude
         *   <i>lat2</i>; this is added automatically;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#LONGITUDE} for the latitude
         *   <i>lon2</i>;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#AZIMUTH} for the latitude
         *   <i>azi2</i>; this is added automatically;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#DISTANCE} for the distance
         *   <i>s12</i>;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#REDUCEDLENGTH} for the reduced length
         *   <i>m12</i>;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#GEODESICSCALE} for the geodesic
         *   scales <i>M12</i> and <i>M21</i>;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#AREA} for the area <i>S12</i>;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#DISTANCE_IN} permits the length of
         *   the geodesic to be given in terms of <i>s12</i>; without this capability
         *   the length can only be specified in terms of arc length;
         * <li>
         *   <i>caps</i> |= {@link GeodesicMask#ALL} for all of the above.
         * </ul>
         **********************************************************************/

        public GeodesicLine(Geodesic g,
                            double lat1, double lon1, double azi1,
                            int caps)
        {
            azi1 = GeoMath.AngNormalize(azi1);
            double salp1, calp1;

            // Guard against underflow in salp0
            {
                Pair p = GeoMath.SinCosD(GeoMath.AngRound(azi1));
                salp1 = p.First; calp1 = p.Second;
            }
            LineInit(g, lat1, lon1, azi1, salp1, calp1, caps);
        }
Пример #2
0
        private void LineInit(Geodesic g,
                              double lat1, double lon1,
                              double azi1, double salp1, double calp1,
                              int caps)
        {
            _a  = g.equatorialRadius;
            _f  = g.ellipsoidFlattening;
            _b  = g._b;
            _c2 = g._c2;
            _f1 = g._f1;
            // Always allow latitude and azimuth and unrolling the longitude
            _caps = caps | GeodesicMask.LATITUDE | GeodesicMask.AZIMUTH |
                    GeodesicMask.LONG_UNROLL;

            _lat1 = GeoMath.LatFix(lat1);
            _lon1 = lon1;
            _azi1 = azi1; _salp1 = salp1; _calp1 = calp1;
            double cbet1, sbet1;

            {
                Pair p = GeoMath.SinCosD(GeoMath.AngRound(_lat1));
                sbet1 = _f1 * p.First; cbet1 = p.Second;
            }
            // Ensure cbet1 = +epsilon at poles
            {
                Pair p = GeoMath.Norm(sbet1, cbet1);
                sbet1 = p.First; cbet1 = Math.Max(Geodesic.tiny_, p.Second);
            }
            _dn1 = Math.Sqrt(1 + g._ep2 * GeoMath.Square(sbet1));

            // Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
            _salp0 = _salp1 * cbet1; // alp0 in [0, pi/2 - |bet1|]
                                     // Alt: calp0 = hypot(sbet1, calp1 * cbet1).  The following
                                     // is slightly better (consider the case salp1 = 0).
            _calp0 = GeoMath.Hypot(_calp1, _salp1 * sbet1);
            // Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
            // sig = 0 is nearest northward crossing of equator.
            // With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
            // With bet1 =  pi/2, alp1 = -pi, sig1 =  pi/2
            // With bet1 = -pi/2, alp1 =  0 , sig1 = -pi/2
            // Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
            // With alp0 in (0, pi/2], quadrants for sig and omg coincide.
            // No atan2(0,0) ambiguity at poles since cbet1 = +epsilon.
            // With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi.
            _ssig1 = sbet1; _somg1 = _salp0 * sbet1;
            _csig1 = _comg1 = sbet1 != 0 || _calp1 != 0 ? cbet1 * _calp1 : 1;
            {
                Pair p = GeoMath.Norm(_ssig1, _csig1);
                _ssig1 = p.First; _csig1 = p.Second;
            } // sig1 in (-pi, pi]
              // GeoMath.norm(_somg1, _comg1); -- don't need to normalize!

            _k2 = GeoMath.Square(_calp0) * g._ep2;
            double eps = _k2 / (2 * (1 + Math.Sqrt(1 + _k2)) + _k2);

            if ((_caps & GeodesicMask.CAP_C1) != 0)
            {
                _A1m1 = Geodesic.A1m1f(eps);
                _C1a  = new double[nC1_ + 1];
                Geodesic.C1f(eps, _C1a);
                _B11 = Geodesic.SinCosSeries(true, _ssig1, _csig1, _C1a);
                double s = Math.Sin(_B11), c = Math.Cos(_B11);
                // tau1 = sig1 + B11
                _stau1 = _ssig1 * c + _csig1 * s;
                _ctau1 = _csig1 * c - _ssig1 * s;
                // Not necessary because C1pa reverts C1a
                //    _B11 = -SinCosSeries(true, _stau1, _ctau1, _C1pa, nC1p_);
            }

            if ((_caps & GeodesicMask.CAP_C1p) != 0)
            {
                _C1pa = new double[nC1p_ + 1];
                Geodesic.C1pf(eps, _C1pa);
            }

            if ((_caps & GeodesicMask.CAP_C2) != 0)
            {
                _C2a  = new double[nC2_ + 1];
                _A2m1 = Geodesic.A2m1f(eps);
                Geodesic.C2f(eps, _C2a);
                _B21 = Geodesic.SinCosSeries(true, _ssig1, _csig1, _C2a);
            }

            if ((_caps & GeodesicMask.CAP_C3) != 0)
            {
                _C3a = new double[nC3_];
                g.C3f(eps, _C3a);
                _A3c = -_f *_salp0 *g.A3f(eps);

                _B31 = Geodesic.SinCosSeries(true, _ssig1, _csig1, _C3a);
            }

            if ((_caps & GeodesicMask.CAP_C4) != 0)
            {
                _C4a = new double[nC4_];
                g.C4f(eps, _C4a);
                // Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0)
                _A4  = GeoMath.Square(_a) * _calp0 * _salp0 * g._e2;
                _B41 = Geodesic.SinCosSeries(false, _ssig1, _csig1, _C4a);
            }
        }