void geod_lineinit_int(geod_geodesic g, double lat1, double lon1, double azi1, double salp1, double calp1, GEOD caps)
		{
			a = g.a;
			f = g.f;
			b = g.b;
			c2 = g.c2;
			f1 = g.f1;

			// If caps is 0 assume the standard direct calculation
			this.caps = (caps != 0 ? caps : GEOD.DISTANCE_IN | GEOD.LONGITUDE) |
				GEOD.LATITUDE | GEOD.AZIMUTH | GEOD.LONG_UNROLL; // always allow latitude and azimuth and unrolling of longitude

			this.lat1 = LatFix(lat1);
			this.lon1 = lon1;
			this.azi1 = azi1;
			this.salp1 = salp1;
			this.calp1 = calp1;

			double cbet1, sbet1;

			sincosdx(AngRound(lat1), out sbet1, out cbet1); sbet1 *= f1;
			// Ensure cbet1 = +epsilon at poles
			norm2(ref sbet1, ref cbet1); cbet1 = maxx(tiny, cbet1);
			dn1 = Math.Sqrt(1 + g.ep2 * sq(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 = hypotx(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;
			norm2(ref ssig1, ref csig1); // sig1 in (-pi, pi]
										 // norm2(somg1, comg1); -- don't need to normalize!

			k2 = sq(calp0) * g.ep2;
			double eps = k2 / (2 * (1 + Math.Sqrt(1 + k2)) + k2);

			if ((this.caps & GEOD.CAP_C1) != 0)
			{
				double s, c;
				A1m1 = geod_geodesic.A1m1f(eps);
				geod_geodesic.C1f(eps, C1a);
				B11 = SinCosSeries(true, ssig1, csig1, C1a, nC1);
				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 ((this.caps & GEOD.CAP_C1p) != 0)
				geod_geodesic.C1pf(eps, C1pa);

			if ((this.caps & GEOD.CAP_C2) != 0)
			{
				A2m1 = geod_geodesic.A2m1f(eps);
				geod_geodesic.C2f(eps, C2a);
				B21 = SinCosSeries(true, ssig1, csig1, C2a, nC2);
			}

			if ((this.caps & GEOD.CAP_C3) != 0)
			{
				g.C3f(eps, C3a);
				A3c = -f * salp0 * g.A3f(eps);
				B31 = SinCosSeries(true, ssig1, csig1, C3a, nC3 - 1);
			}

			if ((this.caps & GEOD.CAP_C4) != 0)
			{
				g.C4f(eps, C4a);
				// Multiplier=a^2*e^2*cos(alpha0)*sin(alpha0)
				A4 = sq(a) * calp0 * salp0 * g.e2;
				B41 = SinCosSeries(false, ssig1, csig1, C4a, nC4);
			}

			a13 = s13 = double.NaN;
		}
Beispiel #2
0
        public override PJ Init()
        {
            g=new geod_geodesic(a, es/(1+Math.Sqrt(one_es)));

            phi0=Proj.pj_param_r(ctx, parameters, "lat_0");
            if(Math.Abs(Math.Abs(phi0)-Proj.HALFPI)<EPS10)
            {
                mode=phi0<0.0?aeqd_mode.S_POLE:aeqd_mode.N_POLE;
                sinph0=phi0<0.0?-1.0:1.0;
                cosph0=0.0;
            }
            else if(Math.Abs(phi0)<EPS10)
            {
                mode=aeqd_mode.EQUIT;
                sinph0=0.0;
                cosph0=1.0;
            }
            else
            {
                mode=aeqd_mode.OBLIQ;
                sinph0=Math.Sin(phi0);
                cosph0=Math.Cos(phi0);
            }

            if(es==0)
            {
                inv=s_inverse;
                fwd=s_forward;
            }
            else
            {
                en=Proj.pj_enfn(es);
                if(en==null) return null;
                if(Proj.pj_param_b(ctx, parameters, "guam"))
                {
                    M1=Proj.pj_mlfn(phi0, sinph0, cosph0, en);
                    inv=e_guam_inv;
                    fwd=e_guam_fwd;
                }
                else
                {
                    switch(mode)
                    {
                        case aeqd_mode.N_POLE:
                            Mp=Proj.pj_mlfn(Proj.HALFPI, 1.0, 0.0, en);
                            break;
                        case aeqd_mode.S_POLE:
                            Mp=Proj.pj_mlfn(-Proj.HALFPI, -1.0, 0.0, en);
                            break;
                        case aeqd_mode.EQUIT:
                        case aeqd_mode.OBLIQ:
                            inv=e_inverse;
                            fwd=e_forward;
                            N1=1.0/Math.Sqrt(1.0-es*sinph0*sinph0);
                            He=e/Math.Sqrt(one_es);
                            G=sinph0*He;
                            He*=cosph0;
                            break;
                    }
                    inv=e_inverse;
                    fwd=e_forward;
                }
            }

            return this;
        }
		/// <summary>
		/// Initialize a geod_geodesicline object in terms of the inverse geodesic problem.
		/// </summary>
		/// <param name="g">The <see cref="geod_geodesic"/> object specifying the ellipsoid.</param>
		/// <param name="lat1">Latitude of point 1 (degrees).</param>
		/// <param name="lon1">Longitude of point 1 (degrees).</param>
		/// <param name="lat2">Latitude of point 2 (degrees).</param>
		/// <param name="lon2">Longitude of point 2 (degrees).</param>
		/// <param name="caps">Bitor'ed combination of <see cref="geod_mask"/> values. See remarks for more informations.</param>
		/// <remarks>
		/// <paramref name="caps"/> bitor'ed combination of geod_mask() values specifying
		/// the capabilities the geod_geodesicline object should possess, i.e., which
		/// quantities can be returned in calls to geod_position() and
		/// geod_genposition().
		///
		/// This function sets point 3 of the geod_geodesicline to correspond to point
		/// 2 of the direct geodesic problem.  See geod_lineinit() for more
		/// information.
		/// </remarks>
		public void geod_inverseline(geod_geodesic g, double lat1, double lon1, double lat2, double lon2, GEOD caps)
		{
			double salp1, calp1, dummy;
			double a12 = g.geod_geninverse_int(lat1, lon1, lat2, lon2, out dummy, out salp1, out calp1, out dummy, out dummy, out dummy, out dummy, out dummy, out dummy);
			double azi1 = atan2dx(salp1, calp1);

			caps = caps != 0 ? caps : GEOD.DISTANCE_IN | GEOD.LONGITUDE;
			// Ensure that a12 can be converted to a distance
			if ((caps & (GEOD.OUT_ALL & GEOD.DISTANCE_IN)) != 0) caps |= GEOD.DISTANCE;
			geod_lineinit_int(g, lat1, lon1, azi1, salp1, calp1, caps);
			geod_setarc(a12);
		}
		/// <summary>
		/// geod_gendirectline : Initialize a geod_geodesicline object in terms of the direct geodesic
		/// problem specified in terms of either distance or arc length.
		/// </summary>
		/// <param name="g">The <see cref="geod_geodesic"/> object specifying the ellipsoid.</param>
		/// <param name="lat1">Latitude of point 1 (degrees).</param>
		/// <param name="lon1">Longitude of point 1 (degrees).</param>
		/// <param name="azi1">Azimuth at point 1 (degrees).</param>
		/// <param name="flags">Must be either <see cref="GEOD.NOFLAGS"/> or <see cref="GEOD.ARCMODE"/> to determining the meaning of the <paramref name="s12_a12"/>.</param>
		/// <param name="s12_a12">if <paramref name="flags"/> = <see cref="GEOD.NOFLAGS"/>, this is the distance from point 1 to point 2 (meters);
		/// if <paramref name="flags"/> = <see cref="GEOD.ARCMODE"/>, it is the arc length from point 1 to point 2 (degrees); it can be negative.</param>
		/// <param name="caps">Bitor'ed combination of <see cref="geod_mask"/> values. See remarks for more informations.</param>
		/// <remarks>
		/// <paramref name="caps"/> bitor'ed combination of geod_mask() values specifying
		/// the capabilities the geod_geodesicline object should possess, i.e., which
		/// quantities can be returned in calls to geod_position() and
		/// geod_genposition().
		///
		/// This function sets point 3 of the geod_geodesicline to correspond to point
		/// 2 of the direct geodesic problem.  See geod_lineinit() for more
		/// information.
		/// </remarks>
		public geod_geodesicline(geod_geodesic g, double lat1, double lon1, double azi1, GEOD flags, double s12_a12, GEOD caps) : this(g, lat1, lon1, azi1, caps)
		{
			geod_gensetdistance(flags, s12_a12);
		}
		/// <summary>
		/// geod_directline : Initialize a geod_geodesicline object in terms of the direct geodesic problem.
		/// </summary>
		/// <param name="g">The <see cref="geod_geodesic"/> object specifying the ellipsoid.</param>
		/// <param name="lat1">Latitude of point 1 (degrees).</param>
		/// <param name="lon1">Longitude of point 1 (degrees).</param>
		/// <param name="azi1">Azimuth at point 1 (degrees).</param>
		/// <param name="s12">Distance from point 1 to point 2 (meters); it can be negative.</param>
		/// <param name="caps">Bitor'ed combination of <see cref="geod_mask"/> values. See remarks for more informations.</param>
		/// <remarks>
		/// <paramref name="caps"/> bitor'ed combination of geod_mask() values specifying
		/// the capabilities the geod_geodesicline object should possess, i.e., which
		/// quantities can be returned in calls to geod_position() and
		/// geod_genposition().
		///
		/// This function sets point 3 of the geod_geodesicline to correspond to point
		/// 2 of the direct geodesic problem.  See geod_lineinit() for more
		/// information.
		/// </remarks>
		public geod_geodesicline(geod_geodesic g, double lat1, double lon1, double azi1, double s12, GEOD caps) : this(g, lat1, lon1, azi1, GEOD.NOFLAGS, s12, caps)
		{ }
		/// <summary>
		/// geod_lineinit : Initialize a geod_geodesicline object.
		/// </summary>
		/// <param name="g">The <see cref="geod_geodesic"/> object specifying the ellipsoid.</param>
		/// <param name="lat1">Latitude of point 1 (degrees).</param>
		/// <param name="lon1">Longitude of point 1 (degrees).</param>
		/// <param name="azi1">Azimuth at point 1 (degrees).</param>
		/// <param name="caps">Bitor'ed combination of <see cref="geod_mask"/> values. See remarks for more informations.</param>
		/// <remarks>
		/// <paramref name="caps"/> bitor'ed combination of geod_mask() values specifying
		/// the capabilities the geod_geodesicline object should possess, i.e., which
		/// quantities can be returned in calls to geod_position() and
		/// geod_genposition().
		///
		/// <paramref name="lat1"/> should be in the range [-90deg, 90deg].
		///
		/// The geod_mask values are:
		/// - caps|=GEOD_LATITUDE for the latitude lat2; this is added automatically,
		/// - caps|=GEOD_LONGITUDE for the latitude lon2,
		/// - caps|=GEOD_AZIMUTH for the latitude azi2; this is added automatically,
		/// - caps|=GEOD_DISTANCE for the distance s12,
		/// - caps|=GEOD_REDUCEDLENGTH for the reduced length m12,
		/// - caps|=GEOD_GEODESICSCALE for the geodesic scales M12 and M21,
		/// - caps|=GEOD_AREA for the area S12,
		/// - caps|=GEOD_DISTANCE_IN permits the length of the
		///   geodesic to be given in terms of s12; without this capability the
		///   length can only be specified in terms of arc length.
		///
		/// A value of caps=0 is treated as GEOD.LATITUDE|GEOD.LONGITUDE|GEOD.AZIMUTH|GEOD.DISTANCE_IN
		/// (to support the solution of the "standard" direct problem).
		///
		/// When initialized by this function, point 3 is undefined (s13 = a13 = NaN).
		/// </remarks>
		public geod_geodesicline(geod_geodesic g, double lat1, double lon1, double azi1, GEOD caps)
		{
			azi1 = AngNormalize(azi1);
			double salp1, calp1;

			// Guard against underflow in salp0
			sincosdx(AngRound(azi1), out salp1, out calp1);
			geod_lineinit_int(g, lat1, lon1, azi1, salp1, calp1, caps);
		}
		public void Ini()
		{
			GlobalGeodesic = new geod_geodesic(geod_a, geod_f);
		}