示例#1
0
        // general inverse projection
        // inverse projection entry
        public static LP pj_inv(XY xy, PJ P)
        {
            LP lp;

            // can't do as much preliminary checking as with forward
            if(xy.x==Libc.HUGE_VAL||xy.y==Libc.HUGE_VAL)
            {
                lp.lam=lp.phi=Libc.HUGE_VAL;
                pj_ctx_set_errno(P.ctx, -15);

                return lp;
            }

            Libc.errno=pj_errno=0;
            P.ctx.last_errno=0;
            xy.x=(xy.x*P.to_meter-P.x0)*P.ra; // descale and de-offset
            xy.y=(xy.y*P.to_meter-P.y0)*P.ra;

            lp=P.inv(xy); // inverse project
            if(P.ctx.last_errno!=0)
            {
                lp.lam=lp.phi=Libc.HUGE_VAL;
            }
            else
            {
                lp.lam+=P.lam0; // reduce from del lp.lam
                if(!P.over) lp.lam=adjlon(lp.lam); // adjust longitude to CM
                if(P.geoc&&Math.Abs(Math.Abs(lp.phi)-HALFPI)>EPS12)
                    lp.phi=Math.Atan(P.one_es*Math.Tan(lp.phi));
            }

            return lp;
        }
示例#2
0
		//**********************************************************************
		//							pj_latlong_from_proj()
		//
		//		Return a PJ* definition defining the lat/long coordinate
		//		system on which a projection is based. If the coordinate
		//		system passed in is latlong, a clone of the same will be
		//		returned.
		//**********************************************************************
		public static PJ pj_latlong_from_proj(PJ pj_in)
		{
			string defn;
			bool got_datum=false;

			pj_errno=0;
			defn="+proj=latlong";

			if(pj_param_t(pj_in.ctx, pj_in.parameters, "datum"))
			{
				got_datum=true;
				defn+=" +datum="+pj_param_s(pj_in.ctx, pj_in.parameters, "datum");
			}
			else if(pj_param_t(pj_in.ctx, pj_in.parameters, "ellps"))
			{
				defn+=" +ellps="+pj_param_s(pj_in.ctx, pj_in.parameters, "ellps");
			}
			else if(pj_param_t(pj_in.ctx, pj_in.parameters, "a"))
			{
				defn+=" +a="+pj_param_s(pj_in.ctx, pj_in.parameters, "a");

				if(pj_param_t(pj_in.ctx, pj_in.parameters, "b")) defn+=" +b="+pj_param_s(pj_in.ctx, pj_in.parameters, "b");
				else if(pj_param_t(pj_in.ctx, pj_in.parameters, "es")) defn+=" +es="+pj_param_s(pj_in.ctx, pj_in.parameters, "es");
				else if(pj_param_t(pj_in.ctx, pj_in.parameters, "f")) defn+=" +f="+pj_param_s(pj_in.ctx, pj_in.parameters, "f");
				else defn+=" +es="+pj_in.es.ToString("G16", nc);
			}
			else
			{
				pj_ctx_set_errno(pj_in.ctx, -13);
				return null;
			}

			if(!got_datum)
			{
				if(pj_param_t(pj_in.ctx, pj_in.parameters, "towgs84")) defn+=" +towgs84="+pj_param_s(pj_in.ctx, pj_in.parameters, "towgs84");
				if(pj_param_t(pj_in.ctx, pj_in.parameters, "nadgrids")) defn+=" +nadgrids="+pj_param_s(pj_in.ctx, pj_in.parameters, "nadgrids");
			}

			// copy over some other information related to ellipsoid
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R")) defn+=" +R="+pj_param_s(pj_in.ctx, pj_in.parameters, "R");

			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R_A")) defn+=" +R_A";
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R_V")) defn+=" +R_V";
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R_a")) defn+=" +R_a";
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R_lat_a")) defn+=" +R_lat_a="+pj_param_s(pj_in.ctx, pj_in.parameters, "R_lat_a");
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "R_lat_g")) defn+=" +R_lat_g="+pj_param_s(pj_in.ctx, pj_in.parameters, "R_lat_g");

			// copy over prime meridian
			if(pj_param_t(pj_in.ctx, pj_in.parameters, "pm")) defn+=" +pm="+pj_param_s(pj_in.ctx, pj_in.parameters, "pm");

			return pj_init_plus_ctx(pj_in.ctx, defn);
		}
示例#3
0
        // general forward projection

        // forward projection entry
        public static XY pj_fwd(LP lp, PJ P)
        {
            XY xy;

            // check for forward and latitude or longitude overange
            double t = Math.Abs(lp.phi) - HALFPI;

            if (t > EPS12 || Math.Abs(lp.lam) > 10.0)
            {
                xy.x = xy.y = Libc.HUGE_VAL;
                pj_ctx_set_errno(P.ctx, -14);
                return(xy);
            }

            // proceed with projection
            Libc.errno       = pj_errno = 0;
            P.ctx.last_errno = 0;
            if (Math.Abs(t) <= EPS12)
            {
                lp.phi = lp.phi < 0.0?-HALFPI:HALFPI;
            }
            else if (P.geoc)
            {
                lp.phi = Math.Atan(P.rone_es * Math.Tan(lp.phi));
            }

            lp.lam -= P.lam0;           // compute del lp.lam
            if (!P.over)
            {
                lp.lam = adjlon(lp.lam); // adjust del longitude
            }
            xy = P.fwd(lp);              // project
            if (P.ctx.last_errno != 0)
            {
                xy.x = xy.y = Libc.HUGE_VAL;
            }
            else             // adjust for major axis and easting/northings
            {
                xy.x = P.fr_meter * (P.a * xy.x + P.x0);
                xy.y = P.fr_meter * (P.a * xy.y + P.y0);
            }

            if (pj_errno == 0)
            {
                pj_errno = Libc.errno;
            }

            return(xy);
        }
示例#4
0
		// general forward projection

		// forward projection entry
		public static XY pj_fwd(LP lp, PJ P)
		{
			XY xy;

			// check for forward and latitude or longitude overange
			double t=Math.Abs(lp.phi)-HALFPI;
			if(t>EPS12||Math.Abs(lp.lam)>10.0)
			{
				xy.x=xy.y=Libc.HUGE_VAL;
				pj_ctx_set_errno(P.ctx, -14);
				return xy;
			}

			// proceed with projection
			Libc.errno=pj_errno=0;
			P.ctx.last_errno=0;
			if(Math.Abs(t)<=EPS12) lp.phi=lp.phi<0.0?-HALFPI:HALFPI;
			else if(P.geoc) lp.phi=Math.Atan(P.rone_es*Math.Tan(lp.phi));

			lp.lam-=P.lam0; // compute del lp.lam
			if(!P.over) lp.lam=adjlon(lp.lam); // adjust del longitude

			// Check for NULL pointer
			if (P.fwd != null)
			{
				xy = P.fwd(lp); // project
				if (P.ctx.last_errno != 0)
				{
					xy.x = xy.y = Libc.HUGE_VAL;
				}
				else // adjust for major axis and easting/northings
				{
					xy.x = P.fr_meter * (P.a * xy.x + P.x0);
					xy.y = P.fr_meter * (P.a * xy.y + P.y0);
				}
			}
			else
			{
				xy.x = xy.y = Libc.HUGE_VAL;
			}

			if(pj_errno==0) pj_errno=Libc.errno;

			return xy;
		}
			0, 0, 0, 0, 0, 0, 0, 0, 1, 0};	// 40 to 49

		//**********************************************************************
		//							pj_transform()
		//
		//		Currently this function doesn't recognise if two projections
		//		are identical (to short circuit reprojection) because it is
		//		difficult to compare PJ structures (since there are some
		//		projection specific components).
		//**********************************************************************
		public static int pj_transform(PJ srcdefn, PJ dstdefn, ref double x, ref double y, ref double z)
		{
			double[] xa=new double[1];
			double[] ya=new double[1];
			double[] za=new double[1];

			xa[0]=x;
			ya[0]=y;
			za[0]=z;

			int ret=pj_transform(srcdefn, dstdefn, 1, 0, xa, ya, za);

			x=xa[0];
			y=ya[0];
			z=za[0];

			return ret;
		}
示例#6
0
        };                                              // 40 to 49

        //**********************************************************************
        //							pj_transform()
        //
        //		Currently this function doesn't recognise if two projections
        //		are identical (to short circuit reprojection) because it is
        //		difficult to compare PJ structures (since there are some
        //		projection specific components).
        //**********************************************************************
        public static int pj_transform(PJ srcdefn, PJ dstdefn, ref double x, ref double y, ref double z)
        {
            double[] xa = new double[1];
            double[] ya = new double[1];
            double[] za = new double[1];

            xa[0] = x;
            ya[0] = y;
            za[0] = z;

            int ret = pj_transform(srcdefn, dstdefn, 1, 0, xa, ya, za);

            x = xa[0];
            y = ya[0];
            z = za[0];

            return(ret);
        }
		public static int pj_transform(PJ srcdefn, PJ dstdefn, double[] x, double[] y, double[] z)
		{
			if(x.Length==y.Length)
			{
				if(x.Length==z.Length)
				{
					int ret=pj_transform(srcdefn, dstdefn, x.Length, 0, x, y, z);
					return ret;
				}
				else
				{
					throw new Exception("Coordinate Arrays had not the same length!");
				}
			}
			else
			{
				throw new Exception("Coordinate Arrays had not the same length!");
			}
		}
示例#8
0
		// general forward projection

		// forward projection entry
		public static XYZ pj_fwd3d(LPZ lpz, PJ P)
		{
			XYZ xyz;

			// check for forward and latitude or longitude overange
			double t = Math.Abs(lpz.phi) - HALFPI;
			if (t > EPS12 || Math.Abs(lpz.lam) > 10.0)
			{
				xyz.x = xyz.y = xyz.z = Libc.HUGE_VAL;
				pj_ctx_set_errno(P.ctx, -14);
				return xyz;
			}

			// proceed with projection
			P.ctx.last_errno = 0;
			pj_errno = 0;
			Libc.errno = 0;

			if (Math.Abs(t) <= EPS12) lpz.phi = lpz.phi < 0.0 ? -HALFPI : HALFPI;
			else if (P.geoc) lpz.phi = Math.Atan(P.rone_es * Math.Tan(lpz.phi)); // Maybe redundant and never used.
			lpz.lam -= P.lam0; // compute del lp.lam
			if (!P.over) lpz.lam = adjlon(lpz.lam); // adjust del longitude

			// Check for NULL pointer
			if (P.fwd3d != null)
			{
				xyz = P.fwd3d(lpz); // project
				if (P.ctx.last_errno != 0) xyz.x = xyz.y = xyz.z = Libc.HUGE_VAL;
				// adjust for major axis and easting/northings
				else
				{
					xyz.x = P.fr_meter * (P.a * xyz.x + P.x0);
					xyz.y = P.fr_meter * (P.a * xyz.y + P.y0);
					// z is not scaled since this handled by vto_meter outside
				}
			}
			else
			{
				xyz.x = xyz.y = xyz.z = Libc.HUGE_VAL;
			}

			return xyz;
		}
示例#9
0
 public static int pj_transform(PJ srcdefn, PJ dstdefn, double[] x, double[] y, double[] z)
 {
     if (x.Length == y.Length)
     {
         if (x.Length == z.Length)
         {
             int ret = pj_transform(srcdefn, dstdefn, x.Length, 0, x, y, z);
             return(ret);
         }
         else
         {
             throw new Exception("Coordinate Arrays had not the same length!");
         }
     }
     else
     {
         throw new Exception("Coordinate Arrays had not the same length!");
     }
 }
示例#10
0
        //**********************************************************************
        //						pj_geocentic_from_wgs84()
        //**********************************************************************
        static int pj_geocentric_from_wgs84(PJ defn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if (defn.datum_type == PJD._3PARAM)
            {
                for (int i = 0; i < point_count; i++)
                {
                    long io = i * point_offset;

                    if (x[io] == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    x[io] = x[io] - defn.datum_params[0];
                    y[io] = y[io] - defn.datum_params[1];
                    z[io] = z[io] - defn.datum_params[2];
                }
            }
            else if (defn.datum_type == PJD._7PARAM)
            {
                for (int i = 0; i < point_count; i++)
                {
                    long   io = i * point_offset;
                    double x_tmp, y_tmp, z_tmp;

                    if (x[io] == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    x_tmp = (x[io] - defn.datum_params[0]) / defn.datum_params[6];
                    y_tmp = (y[io] - defn.datum_params[1]) / defn.datum_params[6];
                    z_tmp = (z[io] - defn.datum_params[2]) / defn.datum_params[6];

                    x[io] = x_tmp + defn.datum_params[5] * y_tmp - defn.datum_params[4] * z_tmp;
                    y[io] = -defn.datum_params[5] * x_tmp + y_tmp + defn.datum_params[3] * z_tmp;
                    z[io] = defn.datum_params[4] * x_tmp - defn.datum_params[3] * y_tmp + z_tmp;
                }
            }

            return(0);
        }
示例#11
0
        //**********************************************************************
        //						pj_geocentic_to_wgs84()
        //**********************************************************************
        static int pj_geocentric_to_wgs84(PJ defn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if (defn.datum_type == PJD._3PARAM)
            {
                for (int i = 0; i < point_count; i++)
                {
                    int io = i * point_offset;

                    if (x[io] == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    x[io] = x[io] + defn.datum_params[0];
                    y[io] = y[io] + defn.datum_params[1];
                    z[io] = z[io] + defn.datum_params[2];
                }
            }
            else if (defn.datum_type == PJD._7PARAM)
            {
                for (int i = 0; i < point_count; i++)
                {
                    int    io = i * point_offset;
                    double x_out, y_out, z_out;

                    if (x[io] == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    x_out = defn.datum_params[6] * (x[io] - defn.datum_params[5] * y[io] + defn.datum_params[4] * z[io]) + defn.datum_params[0];
                    y_out = defn.datum_params[6] * (defn.datum_params[5] * x[io] + y[io] - defn.datum_params[3] * z[io]) + defn.datum_params[1];
                    z_out = defn.datum_params[6] * (-defn.datum_params[4] * x[io] + defn.datum_params[3] * y[io] + z[io]) + defn.datum_params[2];

                    x[io] = x_out;
                    y[io] = y_out;
                    z[io] = z_out;
                }
            }

            return(0);
        }
示例#12
0
		// general inverse projection

		// inverse projection entry
		public static LPZ pj_inv3d(XYZ xyz, PJ P)
		{
			LPZ lpz;

			// can't do as much preliminary checking as with forward
			if (xyz.x == Libc.HUGE_VAL || xyz.y == Libc.HUGE_VAL || xyz.z == Libc.HUGE_VAL)
			{
				lpz.lam = lpz.phi = lpz.z = Libc.HUGE_VAL;
				pj_ctx_set_errno(P.ctx, -15);
				return lpz;
			}

			Libc.errno = pj_errno = 0;
			P.ctx.last_errno = 0;

			xyz.x = (xyz.x * P.to_meter - P.x0) * P.ra; // descale and de-offset
			xyz.y = (xyz.y * P.to_meter - P.y0) * P.ra;
			// z is not scaled since that is handled by vto_meter before we get here

			// Check for NULL pointer
			if (P.inv3d != null)
			{
				lpz = P.inv3d(xyz); // inverse project
				if (P.ctx.last_errno != 0) lpz.lam = lpz.phi = lpz.z = Libc.HUGE_VAL;
				else
				{
					lpz.lam += P.lam0; // reduce from del lp.lam
					if (!P.over) lpz.lam = adjlon(lpz.lam); // adjust longitude to CM

					// This maybe redundant and never used
					if (P.geoc && Math.Abs(Math.Abs(lpz.phi) - HALFPI) > EPS12) lpz.phi = Math.Atan(P.one_es * Math.Tan(lpz.phi));
				}
			}
			else
			{
				lpz.lam = lpz.phi = lpz.z = Libc.HUGE_VAL;
			}

			return lpz;
		}
示例#13
0
        // general inverse projection

        // inverse projection entry
        public static LP pj_inv(XY xy, PJ P)
        {
            LP lp;

            // can't do as much preliminary checking as with forward
            if (xy.x == Libc.HUGE_VAL || xy.y == Libc.HUGE_VAL)
            {
                lp.lam = lp.phi = Libc.HUGE_VAL;
                pj_ctx_set_errno(P.ctx, -15);

                return(lp);
            }

            Libc.errno       = pj_errno = 0;
            P.ctx.last_errno = 0;
            xy.x             = (xy.x * P.to_meter - P.x0) * P.ra; // descale and de-offset
            xy.y             = (xy.y * P.to_meter - P.y0) * P.ra;

            lp = P.inv(xy);           // inverse project
            if (P.ctx.last_errno != 0)
            {
                lp.lam = lp.phi = Libc.HUGE_VAL;
            }
            else
            {
                lp.lam += P.lam0;               // reduce from del lp.lam
                if (!P.over)
                {
                    lp.lam = adjlon(lp.lam);                       // adjust longitude to CM
                }
                if (P.geoc && Math.Abs(Math.Abs(lp.phi) - HALFPI) > EPS12)
                {
                    lp.phi = Math.Atan(P.one_es * Math.Tan(lp.phi));
                }
            }

            return(lp);
        }
示例#14
0
        //**********************************************************************
        //							pj_compare_datums()
        //
        //		Returns true if the two datums are identical, otherwise false
        //**********************************************************************
        public static bool pj_compare_datums(PJ srcdefn, PJ dstdefn)
        {
            if (srcdefn.datum_type != dstdefn.datum_type)
            {
                return(false);
            }

            // the tolerence for es is to ensure that GRS80 and WGS84 are considered identical
            if (srcdefn.a_orig != dstdefn.a_orig || Math.Abs(srcdefn.es_orig - dstdefn.es_orig) > 0.000000000050)
            {
                return(false);
            }

            if (srcdefn.datum_type == PJD._3PARAM)
            {
                return(srcdefn.datum_params[0] == dstdefn.datum_params[0] &&
                       srcdefn.datum_params[1] == dstdefn.datum_params[1] &&
                       srcdefn.datum_params[2] == dstdefn.datum_params[2]);
            }

            if (srcdefn.datum_type == PJD._7PARAM)
            {
                return(srcdefn.datum_params[0] == dstdefn.datum_params[0] &&
                       srcdefn.datum_params[1] == dstdefn.datum_params[1] &&
                       srcdefn.datum_params[2] == dstdefn.datum_params[2] &&
                       srcdefn.datum_params[3] == dstdefn.datum_params[3] &&
                       srcdefn.datum_params[4] == dstdefn.datum_params[4] &&
                       srcdefn.datum_params[5] == dstdefn.datum_params[5] &&
                       srcdefn.datum_params[6] == dstdefn.datum_params[6]);
            }

            if (srcdefn.datum_type == PJD.GRIDSHIFT)
            {
                return(pj_param_s(srcdefn.ctx, srcdefn.parameters, "nadgrids") == pj_param_s(dstdefn.ctx, dstdefn.parameters, "nadgrids"));
            }

            return(true);
        }
示例#15
0
        //**********************************************************************
        //                        pj_geocentic_from_wgs84()
        //**********************************************************************
        static int pj_geocentric_from_wgs84(PJ defn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if(defn.datum_type==PJD._3PARAM)
            {
                for(int i=0; i<point_count; i++)
                {
                    long io=i*point_offset;

                    if(x[io]==Libc.HUGE_VAL) continue;

                    x[io]=x[io]-defn.datum_params[0];
                    y[io]=y[io]-defn.datum_params[1];
                    z[io]=z[io]-defn.datum_params[2];
                }
            }
            else if(defn.datum_type==PJD._7PARAM)
            {
                for(int i=0; i<point_count; i++)
                {
                    long io=i*point_offset;
                    double x_tmp, y_tmp, z_tmp;

                    if(x[io]==Libc.HUGE_VAL) continue;

                    x_tmp=(x[io]-defn.datum_params[0])/defn.datum_params[6];
                    y_tmp=(y[io]-defn.datum_params[1])/defn.datum_params[6];
                    z_tmp=(z[io]-defn.datum_params[2])/defn.datum_params[6];

                    x[io]=x_tmp+defn.datum_params[5]*y_tmp-defn.datum_params[4]*z_tmp;
                    y[io]=-defn.datum_params[5]*x_tmp+y_tmp+defn.datum_params[3]*z_tmp;
                    z[io]=defn.datum_params[4]*x_tmp-defn.datum_params[3]*y_tmp+z_tmp;
                }
            }

            return 0;
        }
示例#16
0
 //**********************************************************************
 //							pj_is_geocent()
 //
 //		Returns TRUE if this coordinate system object is geocentric.
 //**********************************************************************
 public static bool pj_is_geocent(PJ pj)
 {
     return(pj != null && pj.is_geocent);
 }
示例#17
0
        //**********************************************************************
        //							pj_latlong_from_proj()
        //
        //		Return a PJ* definition defining the lat/long coordinate
        //		system on which a projection is based. If the coordinate
        //		system passed in is latlong, a clone of the same will be
        //		returned.
        //**********************************************************************
        public static PJ pj_latlong_from_proj(PJ pj_in)
        {
            string defn;
            bool   got_datum = false;

            pj_errno = 0;
            defn     = "+proj=latlong";

            if (pj_param_t(pj_in.ctx, pj_in.parameters, "datum"))
            {
                got_datum = true;
                defn     += " +datum=" + pj_param_s(pj_in.ctx, pj_in.parameters, "datum");
            }
            else if (pj_param_t(pj_in.ctx, pj_in.parameters, "ellps"))
            {
                defn += " +ellps=" + pj_param_s(pj_in.ctx, pj_in.parameters, "ellps");
            }
            else if (pj_param_t(pj_in.ctx, pj_in.parameters, "a"))
            {
                defn += " +a=" + pj_param_s(pj_in.ctx, pj_in.parameters, "a");

                if (pj_param_t(pj_in.ctx, pj_in.parameters, "b"))
                {
                    defn += " +b=" + pj_param_s(pj_in.ctx, pj_in.parameters, "b");
                }
                else if (pj_param_t(pj_in.ctx, pj_in.parameters, "es"))
                {
                    defn += " +es=" + pj_param_s(pj_in.ctx, pj_in.parameters, "es");
                }
                else if (pj_param_t(pj_in.ctx, pj_in.parameters, "f"))
                {
                    defn += " +f=" + pj_param_s(pj_in.ctx, pj_in.parameters, "f");
                }
                else
                {
                    defn += " +es=" + pj_in.es.ToString("G16");
                }
            }
            else
            {
                pj_ctx_set_errno(pj_in.ctx, -13);
                return(null);
            }

            if (!got_datum)
            {
                if (pj_param_t(pj_in.ctx, pj_in.parameters, "towgs84"))
                {
                    defn += " +towgs84=" + pj_param_s(pj_in.ctx, pj_in.parameters, "towgs84");
                }
                if (pj_param_t(pj_in.ctx, pj_in.parameters, "nadgrids"))
                {
                    defn += " +nadgrids=" + pj_param_s(pj_in.ctx, pj_in.parameters, "nadgrids");
                }
            }

            // copy over some other information related to ellipsoid
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R"))
            {
                defn += " +R=" + pj_param_s(pj_in.ctx, pj_in.parameters, "R");
            }

            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R_A"))
            {
                defn += " +R_A";
            }
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R_V"))
            {
                defn += " +R_V";
            }
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R_a"))
            {
                defn += " +R_a";
            }
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R_lat_a"))
            {
                defn += " +R_lat_a=" + pj_param_s(pj_in.ctx, pj_in.parameters, "R_lat_a");
            }
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "R_lat_g"))
            {
                defn += " +R_lat_g=" + pj_param_s(pj_in.ctx, pj_in.parameters, "R_lat_g");
            }

            // copy over prime meridian
            if (pj_param_t(pj_in.ctx, pj_in.parameters, "pm"))
            {
                defn += " +pm=" + pj_param_s(pj_in.ctx, pj_in.parameters, "pm");
            }

            return(pj_init_plus_ctx(pj_in.ctx, defn));
        }
示例#18
0
        //**********************************************************************
        //							pj_datum_transform()
        //
        //		The input should be long/lat/z coordinates in radians in the
        //		source datum, and the output should be long/lat/z
        //		coordinates in radians in the destination datum.
        //**********************************************************************
        public static int pj_datum_transform(PJ srcdefn, PJ dstdefn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            const double SRS_WGS84_SEMIMAJOR = 6378137.0;
            const double SRS_WGS84_ESQUARED  = 0.0066943799901413165;

            // --------------------------------------------------------------------
            //		We cannot do any meaningful datum transformation if either
            //		the source or destination are of an unknown datum type
            //		(ie. only a +ellps declaration, no +datum). This is new
            //		behavior for PROJ 4.6.0.
            // --------------------------------------------------------------------
            if (srcdefn.datum_type == PJD.UNKNOWN || dstdefn.datum_type == PJD.UNKNOWN)
            {
                return(0);
            }

            // --------------------------------------------------------------------
            //		Short cut if the datums are identical.
            // --------------------------------------------------------------------
            if (pj_compare_datums(srcdefn, dstdefn))
            {
                return(0);
            }

            double src_a  = srcdefn.a_orig;
            double src_es = srcdefn.es_orig;

            double dst_a  = dstdefn.a_orig;
            double dst_es = dstdefn.es_orig;

            // --------------------------------------------------------------------
            //		Create a temporary Z array if one is not provided.
            // --------------------------------------------------------------------
            if (z == null)
            {
                z = new double[point_count * point_offset];
            }

            // --------------------------------------------------------------------
            //		If this datum requires grid shifts, then apply it to geodetic
            //		coordinates.
            // --------------------------------------------------------------------
            if (srcdefn.datum_type == PJD.GRIDSHIFT)
            {
                Grid.pj_apply_gridshift_2(srcdefn, false, point_count, point_offset, x, y, z);
                if (srcdefn.ctx.last_errno != 0 && (srcdefn.ctx.last_errno > 0 || transient_error[-srcdefn.ctx.last_errno] == 0))
                {
                    return(srcdefn.ctx.last_errno);
                }

                src_a  = SRS_WGS84_SEMIMAJOR;
                src_es = SRS_WGS84_ESQUARED;
            }

            if (dstdefn.datum_type == PJD.GRIDSHIFT)
            {
                dst_a  = SRS_WGS84_SEMIMAJOR;
                dst_es = SRS_WGS84_ESQUARED;
            }

            // ====================================================================
            //		Do we need to go through geocentric coordinates?
            // ====================================================================
            if (src_es != dst_es || src_a != dst_a || srcdefn.datum_type == PJD._3PARAM || srcdefn.datum_type == PJD._7PARAM ||
                dstdefn.datum_type == PJD._3PARAM || dstdefn.datum_type == PJD._7PARAM)
            {
                // --------------------------------------------------------------------
                //		Convert to geocentric coordinates.
                // --------------------------------------------------------------------
                srcdefn.ctx.last_errno = pj_geodetic_to_geocentric(src_a, src_es, point_count, point_offset, x, y, z);
                if (srcdefn.ctx.last_errno != 0 && (srcdefn.ctx.last_errno > 0 || transient_error[-srcdefn.ctx.last_errno] == 0))
                {
                    return(srcdefn.ctx.last_errno);
                }

                // --------------------------------------------------------------------
                //		Convert between datums.
                // --------------------------------------------------------------------
                if (srcdefn.datum_type == PJD._3PARAM || srcdefn.datum_type == PJD._7PARAM)
                {
                    pj_geocentric_to_wgs84(srcdefn, point_count, point_offset, x, y, z);
                    if (srcdefn.ctx.last_errno != 0 && (srcdefn.ctx.last_errno > 0 || transient_error[-srcdefn.ctx.last_errno] == 0))
                    {
                        return(srcdefn.ctx.last_errno);
                    }
                }

                if (dstdefn.datum_type == PJD._3PARAM || dstdefn.datum_type == PJD._7PARAM)
                {
                    pj_geocentric_from_wgs84(dstdefn, point_count, point_offset, x, y, z);
                    if (dstdefn.ctx.last_errno != 0 && (dstdefn.ctx.last_errno > 0 || transient_error[-dstdefn.ctx.last_errno] == 0))
                    {
                        return(dstdefn.ctx.last_errno);
                    }
                }

                // --------------------------------------------------------------------
                //		Convert back to geodetic coordinates.
                // --------------------------------------------------------------------
                dstdefn.ctx.last_errno = pj_geocentric_to_geodetic(dst_a, dst_es, point_count, point_offset, x, y, z);
                if (dstdefn.ctx.last_errno != 0 && (dstdefn.ctx.last_errno > 0 || transient_error[-dstdefn.ctx.last_errno] == 0))
                {
                    return(dstdefn.ctx.last_errno);
                }
            }

            // --------------------------------------------------------------------
            //		Apply grid shift to destination if required.
            // --------------------------------------------------------------------
            if (dstdefn.datum_type == PJD.GRIDSHIFT)
            {
                Grid.pj_apply_gridshift_2(dstdefn, true, point_count, point_offset, x, y, z);
                if (dstdefn.ctx.last_errno != 0 && (dstdefn.ctx.last_errno > 0 || transient_error[-dstdefn.ctx.last_errno] == 0))
                {
                    return(dstdefn.ctx.last_errno);
                }
            }

            return(0);
        }
示例#19
0
		//**********************************************************************
		//						pj_get_spheroid_defn()
		//
		//		Fetch the internal definition of the spheroid. Note that
		//		you can compute "b" from eccentricity_squared as:
		//
		//		b=a*sqrt(1-es)
		//**********************************************************************
		public static void pj_get_spheroid_defn(PJ defn, out double major_axis, out double eccentricity_squared)
		{
			major_axis=defn.a;
			eccentricity_squared=defn.es;
		}
示例#20
0
		//**********************************************************************
		//							pj_is_latlong()
		//
		//		Returns TRUE if this coordinate system object is geographic.
		//**********************************************************************
		public static bool pj_is_latlong(PJ pj)
		{
			return pj==null||pj.is_latlong;
		}
示例#21
0
        public static int pj_transform(PJ srcdefn, PJ dstdefn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            srcdefn.ctx.last_errno = 0;
            dstdefn.ctx.last_errno = 0;

            if (point_offset == 0)
            {
                point_offset = 1;
            }

            // --------------------------------------------------------------------
            //		Transform unusual input coordinate axis orientation to
            //		standard form if needed.
            // --------------------------------------------------------------------
            if (srcdefn.axis != "enu")
            {
                int err = pj_adjust_axis(srcdefn.ctx, srcdefn.axis, false, point_count, point_offset, x, y, z);
                if (err != 0)
                {
                    return(err);
                }
            }

            // --------------------------------------------------------------------
            //		Transform Z to meters if it isn't already.
            // --------------------------------------------------------------------
            if (srcdefn.vto_meter != 1.0 && z != null)
            {
                for (int i = 0; i < point_count; i++)
                {
                    z[point_offset * i] *= srcdefn.vto_meter;
                }
            }

            // --------------------------------------------------------------------
            //		Transform geocentric source coordinates to lat/long.
            // --------------------------------------------------------------------
            if (srcdefn.is_geocent)
            {
                if (z == null)
                {
                    pj_ctx_set_errno(pj_get_ctx(srcdefn), (int)PJD_ERR.GEOCENTRIC);
                    return((int)PJD_ERR.GEOCENTRIC);
                }

                if (srcdefn.to_meter != 1.0)
                {
                    for (int i = 0; i < point_count; i++)
                    {
                        if (x[point_offset * i] != Libc.HUGE_VAL)
                        {
                            x[point_offset * i] *= srcdefn.to_meter;
                            y[point_offset * i] *= srcdefn.to_meter;
                        }
                    }
                }

                int err = pj_geocentric_to_geodetic(srcdefn.a_orig, srcdefn.es_orig, point_count, point_offset, x, y, z);
                if (err != 0)
                {
                    return(err);
                }
            }
            // --------------------------------------------------------------------
            //		Transform source points to lat/long, if they aren't
            //		already.
            // --------------------------------------------------------------------
            else if (!srcdefn.is_latlong)
            {
                if (srcdefn.inv == null)
                {
                    pj_ctx_set_errno(pj_get_ctx(srcdefn), -17);
#if DEBUG
                    Console.Error.WriteLine("pj_transform(): source projection not invertable");
#endif

                    return(-17);
                }

                for (int i = 0; i < point_count; i++)
                {
                    XY projected_loc;
                    LP geodetic_loc;

                    projected_loc.x = x[point_offset * i];
                    projected_loc.y = y[point_offset * i];

                    if (projected_loc.x == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    geodetic_loc = pj_inv(projected_loc, srcdefn);
                    if (srcdefn.ctx.last_errno != 0)
                    {
                        if ((srcdefn.ctx.last_errno != (int)ERRORNUMBER.EDOM && srcdefn.ctx.last_errno != (int)ERRORNUMBER.ERANGE) &&
                            (srcdefn.ctx.last_errno > 0 || srcdefn.ctx.last_errno < -49 || point_count == 1 || transient_error[-srcdefn.ctx.last_errno] == 0))
                        {
                            return(srcdefn.ctx.last_errno);
                        }

                        geodetic_loc.lam = Libc.HUGE_VAL;
                        geodetic_loc.phi = Libc.HUGE_VAL;
                    }

                    x[point_offset * i] = geodetic_loc.lam;
                    y[point_offset * i] = geodetic_loc.phi;
                }
            }

            // --------------------------------------------------------------------
            //		But if they are already lat long, adjust for the prime
            //		meridian if there is one in effect.
            // --------------------------------------------------------------------
            if (srcdefn.from_greenwich != 0.0)
            {
                for (int i = 0; i < point_count; i++)
                {
                    if (x[point_offset * i] != Libc.HUGE_VAL)
                    {
                        x[point_offset * i] += srcdefn.from_greenwich;
                    }
                }
            }

            // --------------------------------------------------------------------
            //		Do we need to translate from geoid to ellipsoidal vertical
            //		datum?
            // --------------------------------------------------------------------
            if (srcdefn.has_geoid_vgrids)
            {
                if (Grid.pj_apply_vgridshift(srcdefn, "geoidgrids", ref srcdefn.vgridlist_geoid, ref srcdefn.vgridlist_geoid_count, false, point_count, point_offset, x, y, z) != 0)
                {
                    return(pj_ctx_get_errno(srcdefn.ctx));
                }
            }

            // --------------------------------------------------------------------
            //		Convert datums if needed, and possible.
            // --------------------------------------------------------------------
            if (pj_datum_transform(srcdefn, dstdefn, point_count, point_offset, x, y, z) != 0)
            {
                if (srcdefn.ctx.last_errno != 0)
                {
                    return(srcdefn.ctx.last_errno);
                }
                else
                {
                    return(dstdefn.ctx.last_errno);
                }
            }

            // --------------------------------------------------------------------
            //		Do we need to translate from geoid to ellipsoidal vertical
            //		datum?
            // --------------------------------------------------------------------
            if (dstdefn.has_geoid_vgrids)
            {
                if (Grid.pj_apply_vgridshift(dstdefn, "geoidgrids", ref dstdefn.vgridlist_geoid, ref dstdefn.vgridlist_geoid_count, true, point_count, point_offset, x, y, z) != 0)
                {
                    return(dstdefn.ctx.last_errno);
                }
            }

            // --------------------------------------------------------------------
            //		But if they are staying lat long, adjust for the prime
            //		meridian if there is one in effect.
            // --------------------------------------------------------------------
            if (dstdefn.from_greenwich != 0.0)
            {
                for (int i = 0; i < point_count; i++)
                {
                    if (x[point_offset * i] != Libc.HUGE_VAL)
                    {
                        x[point_offset * i] -= dstdefn.from_greenwich;
                    }
                }
            }

            // --------------------------------------------------------------------
            //		Transform destination latlong to geocentric if required.
            // --------------------------------------------------------------------
            if (dstdefn.is_geocent)
            {
                if (z == null)
                {
                    pj_ctx_set_errno(dstdefn.ctx, (int)PJD_ERR.GEOCENTRIC);
                    return((int)PJD_ERR.GEOCENTRIC);
                }

                pj_geodetic_to_geocentric(dstdefn.a_orig, dstdefn.es_orig, point_count, point_offset, x, y, z);

                if (dstdefn.fr_meter != 1.0)
                {
                    for (int i = 0; i < point_count; i++)
                    {
                        if (x[point_offset * i] != Libc.HUGE_VAL)
                        {
                            x[point_offset * i] *= dstdefn.fr_meter;
                            y[point_offset * i] *= dstdefn.fr_meter;
                        }
                    }
                }
            }
            // --------------------------------------------------------------------
            //		Transform destination points to projection coordinates, if
            //		desired.
            // --------------------------------------------------------------------
            else if (!dstdefn.is_latlong)
            {
                for (int i = 0; i < point_count; i++)
                {
                    XY projected_loc;
                    LP geodetic_loc;

                    geodetic_loc.lam = x[point_offset * i];
                    geodetic_loc.phi = y[point_offset * i];

                    if (geodetic_loc.lam == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    projected_loc = pj_fwd(geodetic_loc, dstdefn);
                    if (dstdefn.ctx.last_errno != 0)
                    {
                        if ((dstdefn.ctx.last_errno != (int)ERRORNUMBER.EDOM && dstdefn.ctx.last_errno != (int)ERRORNUMBER.ERANGE) &&
                            (dstdefn.ctx.last_errno > 0 || dstdefn.ctx.last_errno < -49 || point_count == 1 || transient_error[-dstdefn.ctx.last_errno] == 0))
                        {
                            return(dstdefn.ctx.last_errno);
                        }

                        projected_loc.x = Libc.HUGE_VAL;
                        projected_loc.y = Libc.HUGE_VAL;
                    }

                    x[point_offset * i] = projected_loc.x;
                    y[point_offset * i] = projected_loc.y;
                }
            }

            // --------------------------------------------------------------------
            //		If a wrapping center other than 0 is provided, rewrap around
            //		the suggested center (for latlong coordinate systems only).
            // --------------------------------------------------------------------
            else if (dstdefn.is_latlong && dstdefn.is_long_wrap_set)
            {
                for (int i = 0; i < point_count; i++)
                {
                    if (x[point_offset * i] == Libc.HUGE_VAL)
                    {
                        continue;
                    }

                    while (x[point_offset * i] < dstdefn.long_wrap_center - PI)
                    {
                        x[point_offset * i] += TWOPI;
                    }
                    while (x[point_offset * i] > dstdefn.long_wrap_center + PI)
                    {
                        x[point_offset * i] -= TWOPI;
                    }
                }
            }

            // --------------------------------------------------------------------
            //		Transform Z from meters if needed.
            // --------------------------------------------------------------------
            if (dstdefn.vto_meter != 1.0 && z != null)
            {
                for (int i = 0; i < point_count; i++)
                {
                    z[point_offset * i] *= dstdefn.vfr_meter;
                }
            }

            // --------------------------------------------------------------------
            //		Transform normalized axes into unusual output coordinate axis
            //		orientation if needed.
            // --------------------------------------------------------------------
            if (dstdefn.axis != "enu")
            {
                int err = pj_adjust_axis(dstdefn.ctx, dstdefn.axis, true, point_count, point_offset, x, y, z);
                if (err != 0)
                {
                    return(err);
                }
            }

            return(0);
        }
示例#22
0
 //**********************************************************************
 //							pj_is_latlong()
 //
 //		Returns TRUE if this coordinate system object is geographic.
 //**********************************************************************
 public static bool pj_is_latlong(PJ pj)
 {
     return(pj == null || pj.is_latlong);
 }
示例#23
0
        //**********************************************************************
        //                            pj_datum_transform()
        //
        //        The input should be long/lat/z coordinates in radians in the
        //        source datum, and the output should be long/lat/z
        //        coordinates in radians in the destination datum.
        //**********************************************************************
        public static int pj_datum_transform(PJ srcdefn, PJ dstdefn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            const double SRS_WGS84_SEMIMAJOR=6378137.0;
            const double SRS_WGS84_ESQUARED=0.0066943799901413165;

            // --------------------------------------------------------------------
            //		We cannot do any meaningful datum transformation if either
            //		the source or destination are of an unknown datum type
            //		(ie. only a +ellps declaration, no +datum). This is new
            //		behavior for PROJ 4.6.0.
            // --------------------------------------------------------------------
            if(srcdefn.datum_type==PJD.UNKNOWN||dstdefn.datum_type==PJD.UNKNOWN) return 0;

            // --------------------------------------------------------------------
            //		Short cut if the datums are identical.
            // --------------------------------------------------------------------
            if(pj_compare_datums(srcdefn, dstdefn)) return 0;

            double src_a=srcdefn.a_orig;
            double src_es=srcdefn.es_orig;

            double dst_a=dstdefn.a_orig;
            double dst_es=dstdefn.es_orig;

            // --------------------------------------------------------------------
            //		Create a temporary Z array if one is not provided.
            // --------------------------------------------------------------------
            if(z==null) z=new double[point_count*point_offset];

            // --------------------------------------------------------------------
            //		If this datum requires grid shifts, then apply it to geodetic
            //		coordinates.
            // --------------------------------------------------------------------
            if(srcdefn.datum_type==PJD.GRIDSHIFT)
            {
                Grid.pj_apply_gridshift_2(srcdefn, false, point_count, point_offset, x, y, z);
                if(srcdefn.ctx.last_errno!=0&&(srcdefn.ctx.last_errno>0||transient_error[-srcdefn.ctx.last_errno]==0)) return srcdefn.ctx.last_errno;

                src_a=SRS_WGS84_SEMIMAJOR;
                src_es=SRS_WGS84_ESQUARED;
            }

            if(dstdefn.datum_type==PJD.GRIDSHIFT)
            {
                dst_a=SRS_WGS84_SEMIMAJOR;
                dst_es=SRS_WGS84_ESQUARED;
            }

            // ====================================================================
            //		Do we need to go through geocentric coordinates?
            // ====================================================================
            if(src_es!=dst_es||src_a!=dst_a||srcdefn.datum_type==PJD._3PARAM||srcdefn.datum_type==PJD._7PARAM||
                dstdefn.datum_type==PJD._3PARAM||dstdefn.datum_type==PJD._7PARAM)
            {
                // --------------------------------------------------------------------
                //		Convert to geocentric coordinates.
                // --------------------------------------------------------------------
                srcdefn.ctx.last_errno=pj_geodetic_to_geocentric(src_a, src_es, point_count, point_offset, x, y, z);
                if(srcdefn.ctx.last_errno!=0&&(srcdefn.ctx.last_errno>0||transient_error[-srcdefn.ctx.last_errno]==0)) return srcdefn.ctx.last_errno;

                // --------------------------------------------------------------------
                //		Convert between datums.
                // --------------------------------------------------------------------
                if(srcdefn.datum_type==PJD._3PARAM||srcdefn.datum_type==PJD._7PARAM)
                {
                    pj_geocentric_to_wgs84(srcdefn, point_count, point_offset, x, y, z);
                    if(srcdefn.ctx.last_errno!=0&&(srcdefn.ctx.last_errno>0||transient_error[-srcdefn.ctx.last_errno]==0)) return srcdefn.ctx.last_errno;
                }

                if(dstdefn.datum_type==PJD._3PARAM||dstdefn.datum_type==PJD._7PARAM)
                {
                    pj_geocentric_from_wgs84(dstdefn, point_count, point_offset, x, y, z);
                    if(dstdefn.ctx.last_errno!=0&&(dstdefn.ctx.last_errno>0||transient_error[-dstdefn.ctx.last_errno]==0)) return dstdefn.ctx.last_errno;
                }

                // --------------------------------------------------------------------
                //		Convert back to geodetic coordinates.
                // --------------------------------------------------------------------
                dstdefn.ctx.last_errno=pj_geocentric_to_geodetic(dst_a, dst_es, point_count, point_offset, x, y, z);
                if(dstdefn.ctx.last_errno!=0&&(dstdefn.ctx.last_errno>0||transient_error[-dstdefn.ctx.last_errno]==0)) return dstdefn.ctx.last_errno;
            }

            // --------------------------------------------------------------------
            //		Apply grid shift to destination if required.
            // --------------------------------------------------------------------
            if(dstdefn.datum_type==PJD.GRIDSHIFT)
            {
                Grid.pj_apply_gridshift_2(dstdefn, true, point_count, point_offset, x, y, z);
                if(dstdefn.ctx.last_errno!=0&&(dstdefn.ctx.last_errno>0||transient_error[-dstdefn.ctx.last_errno]==0)) return dstdefn.ctx.last_errno;
            }

            return 0;
        }
示例#24
0
        //**********************************************************************
        //                            pj_datum_set()
        //**********************************************************************
        static bool pj_datum_set(projCtx ctx, List<string> pl, PJ projdef)
        {
            projdef.datum_type=PJD.UNKNOWN;

            // --------------------------------------------------------------------
            //		Is there a datum definition in the parameters list? If so,
            //		add the defining values to the parameter list. Note that
            //		this will append the ellipse definition as well as the
            //		towgs84= and related parameters. It should also be pointed
            //		out that the addition is permanent rather than temporary
            //		like most other keyword expansion so that the ellipse
            //		definition will last into the pj_ell_set() function called
            //		after this one.
            // --------------------------------------------------------------------
            string name=pj_param_s(ctx, pl, "datum");
            if(name!=null&&name!="")
            {
                string defn, ellipse_id;
                if(GetDatum(name, out defn, out ellipse_id)==null) { pj_ctx_set_errno(ctx, -9); return true; }

                if(ellipse_id!=null&&ellipse_id.Length>0) pl.Add(pj_mkparam("ellps="+ellipse_id));
                if(defn!=null&&defn.Length>0) pl.Add(pj_mkparam(defn));
            }

            string nadgrids=pj_param_s(ctx, pl, "nadgrids");
            string towgs84=pj_param_s(ctx, pl, "towgs84");
            string catalog=pj_param_s(ctx, pl, "catalog");

            // --------------------------------------------------------------------
            //		Check for nadgrids parameter.
            // --------------------------------------------------------------------
            if(!string.IsNullOrEmpty(nadgrids))
            {
                // We don't actually save the value separately. It will continue
                // to exist in the param list for use in pj_apply_gridshift.cs
                projdef.datum_type=PJD.GRIDSHIFT;
            }

            // --------------------------------------------------------------------
            //		Check for grid catalog parameter, and optional date.
            // --------------------------------------------------------------------
            else if(!string.IsNullOrEmpty(catalog))
            {
                projdef.datum_type=PJD.GRIDSHIFT;
                projdef.catalog_name=catalog;

                string date=pj_param_s(ctx, pl, "date");
                if(!string.IsNullOrEmpty(date)) projdef.datum_date=Free.Ports.Proj4.Gridshift.Grid.pj_gc_parsedate(ctx, date);
            }

            // --------------------------------------------------------------------
            //		Check for towgs84 parameter.
            // --------------------------------------------------------------------
            else if(!string.IsNullOrEmpty(towgs84))
            {
                projdef.datum_params[0]=projdef.datum_params[1]=projdef.datum_params[2]=0;
                projdef.datum_params[3]=projdef.datum_params[4]=projdef.datum_params[5]=projdef.datum_params[6]=0;

                // parse out the parameters
                string s=towgs84;
                string[] ss=s.Split(',');
                for(int i=0; i<7&&i<ss.Length; i++) projdef.datum_params[i]=double.Parse(ss[i], nc);

                if(projdef.datum_params[3]!=0.0||projdef.datum_params[4]!=0.0||projdef.datum_params[5]!=0.0||projdef.datum_params[6]!=0.0)
                {
                    projdef.datum_type=PJD._7PARAM;

                    // transform from arc seconds to radians
                    projdef.datum_params[3]*=SEC_TO_RAD;
                    projdef.datum_params[4]*=SEC_TO_RAD;
                    projdef.datum_params[5]*=SEC_TO_RAD;

                    // transform from parts per million to scaling factor
                    projdef.datum_params[6]=(projdef.datum_params[6]/1000000.0)+1;
                }
                else projdef.datum_type=PJD._3PARAM;

                // Note that pj_init() will later switch datum_type to PJD.WGS84 if shifts are all zero, and ellipsoid is WGS84 or GRS80
            }

            return false;
        }
示例#25
0
		//**********************************************************************
		//							pj_is_geocent()
		//
		//		Returns TRUE if this coordinate system object is geocentric.
		//**********************************************************************
		public static bool pj_is_geocent(PJ pj)
		{
			return pj!=null&&pj.is_geocent;
		}
示例#26
0
        //**********************************************************************
        //                            pj_compare_datums()
        //
        //        Returns true if the two datums are identical, otherwise false
        //**********************************************************************
        public static bool pj_compare_datums(PJ srcdefn, PJ dstdefn)
        {
            if(srcdefn.datum_type!=dstdefn.datum_type) return false;

            // the tolerence for es is to ensure that GRS80 and WGS84 are considered identical
            if(srcdefn.a_orig!=dstdefn.a_orig||Math.Abs(srcdefn.es_orig-dstdefn.es_orig)>0.000000000050) return false;

            if(srcdefn.datum_type==PJD._3PARAM)
                return (srcdefn.datum_params[0]==dstdefn.datum_params[0]&&
                        srcdefn.datum_params[1]==dstdefn.datum_params[1]&&
                        srcdefn.datum_params[2]==dstdefn.datum_params[2]);

            if(srcdefn.datum_type==PJD._7PARAM)
                return (srcdefn.datum_params[0]==dstdefn.datum_params[0]&&
                        srcdefn.datum_params[1]==dstdefn.datum_params[1]&&
                        srcdefn.datum_params[2]==dstdefn.datum_params[2]&&
                        srcdefn.datum_params[3]==dstdefn.datum_params[3]&&
                        srcdefn.datum_params[4]==dstdefn.datum_params[4]&&
                        srcdefn.datum_params[5]==dstdefn.datum_params[5]&&
                        srcdefn.datum_params[6]==dstdefn.datum_params[6]);

            if(srcdefn.datum_type==PJD.GRIDSHIFT)
                return pj_param_s(srcdefn.ctx, srcdefn.parameters, "nadgrids")==pj_param_s(dstdefn.ctx, dstdefn.parameters, "nadgrids");

            return true;
        }
示例#27
0
        //**********************************************************************
        //							pj_datum_set()
        //**********************************************************************
        static bool pj_datum_set(projCtx ctx, List <string> pl, PJ projdef)
        {
            projdef.datum_type = PJD.UNKNOWN;

            // --------------------------------------------------------------------
            //		Is there a datum definition in the parameters list? If so,
            //		add the defining values to the parameter list. Note that
            //		this will append the ellipse definition as well as the
            //		towgs84= and related parameters. It should also be pointed
            //		out that the addition is permanent rather than temporary
            //		like most other keyword expansion so that the ellipse
            //		definition will last into the pj_ell_set() function called
            //		after this one.
            // --------------------------------------------------------------------
            string name = pj_param_s(ctx, pl, "datum");

            if (name != null && name != "")
            {
                string defn, ellipse_id;
                if (GetDatum(name, out defn, out ellipse_id) == null)
                {
                    pj_ctx_set_errno(ctx, -9); return(true);
                }

                if (ellipse_id != null && ellipse_id.Length > 0)
                {
                    pl.Add(pj_mkparam("ellps=" + ellipse_id));
                }
                if (defn != null && defn.Length > 0)
                {
                    pl.Add(pj_mkparam(defn));
                }
            }

            string nadgrids = pj_param_s(ctx, pl, "nadgrids");
            string towgs84  = pj_param_s(ctx, pl, "towgs84");
            string catalog  = pj_param_s(ctx, pl, "catalog");

            // --------------------------------------------------------------------
            //		Check for nadgrids parameter.
            // --------------------------------------------------------------------
            if (!string.IsNullOrEmpty(nadgrids))
            {
                // We don't actually save the value separately. It will continue
                // to exist in the param list for use in pj_apply_gridshift.cs
                projdef.datum_type = PJD.GRIDSHIFT;
            }

            // --------------------------------------------------------------------
            //		Check for grid catalog parameter, and optional date.
            // --------------------------------------------------------------------
            else if (!string.IsNullOrEmpty(catalog))
            {
                projdef.datum_type   = PJD.GRIDSHIFT;
                projdef.catalog_name = catalog;

                string date = pj_param_s(ctx, pl, "date");
                if (!string.IsNullOrEmpty(date))
                {
                    projdef.datum_date = Free.Ports.Proj4.Gridshift.Grid.pj_gc_parsedate(ctx, date);
                }
            }

            // --------------------------------------------------------------------
            //		Check for towgs84 parameter.
            // --------------------------------------------------------------------
            else if (!string.IsNullOrEmpty(towgs84))
            {
                projdef.datum_params[0] = projdef.datum_params[1] = projdef.datum_params[2] = 0;
                projdef.datum_params[3] = projdef.datum_params[4] = projdef.datum_params[5] = projdef.datum_params[6] = 0;

                // parse out the parameters
                string   s  = towgs84;
                string[] ss = s.Split(',');
                for (int i = 0; i < 7 && i < ss.Length; i++)
                {
                    projdef.datum_params[i] = double.Parse(ss[i], nc);
                }

                if (projdef.datum_params[3] != 0.0 || projdef.datum_params[4] != 0.0 || projdef.datum_params[5] != 0.0 || projdef.datum_params[6] != 0.0)
                {
                    projdef.datum_type = PJD._7PARAM;

                    // transform from arc seconds to radians
                    projdef.datum_params[3] *= SEC_TO_RAD;
                    projdef.datum_params[4] *= SEC_TO_RAD;
                    projdef.datum_params[5] *= SEC_TO_RAD;

                    // transform from parts per million to scaling factor
                    projdef.datum_params[6] = (projdef.datum_params[6] / 1000000.0) + 1;
                }
                else
                {
                    projdef.datum_type = PJD._3PARAM;
                }

                // Note that pj_init() will later switch datum_type to PJD.WGS84 if shifts are all zero, and ellipsoid is WGS84 or GRS80
            }

            return(false);
        }
示例#28
0
        public static int pj_transform(PJ srcdefn, PJ dstdefn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            srcdefn.ctx.last_errno=0;
            dstdefn.ctx.last_errno=0;

            if(point_offset==0) point_offset=1;

            // --------------------------------------------------------------------
            //		Transform unusual input coordinate axis orientation to
            //		standard form if needed.
            // --------------------------------------------------------------------
            if(srcdefn.axis!="enu")
            {
                int err=pj_adjust_axis(srcdefn.ctx, srcdefn.axis, false, point_count, point_offset, x, y, z);
                if(err!=0) return err;
            }

            // --------------------------------------------------------------------
            //		Transform Z to meters if it isn't already.
            // --------------------------------------------------------------------
            if(srcdefn.vto_meter!=1.0&&z!=null)
            {
                for(int i=0; i<point_count; i++) z[point_offset*i]*=srcdefn.vto_meter;
            }

            // --------------------------------------------------------------------
            //		Transform geocentric source coordinates to lat/long.
            // --------------------------------------------------------------------
            if(srcdefn.is_geocent)
            {
                if(z==null)
                {
                    pj_ctx_set_errno(pj_get_ctx(srcdefn), (int)PJD_ERR.GEOCENTRIC);
                    return (int)PJD_ERR.GEOCENTRIC;
                }

                if(srcdefn.to_meter!=1.0)
                {
                    for(int i=0; i<point_count; i++)
                    {
                        if(x[point_offset*i]!=Libc.HUGE_VAL)
                        {
                            x[point_offset*i]*=srcdefn.to_meter;
                            y[point_offset*i]*=srcdefn.to_meter;
                        }
                    }
                }

                int err=pj_geocentric_to_geodetic(srcdefn.a_orig, srcdefn.es_orig, point_count, point_offset, x, y, z);
                if(err!=0) return err;
            }
            // --------------------------------------------------------------------
            //		Transform source points to lat/long, if they aren't
            //		already.
            // --------------------------------------------------------------------
            else if(!srcdefn.is_latlong)
            {
                if(srcdefn.inv==null)
                {
                    pj_ctx_set_errno(pj_get_ctx(srcdefn), -17);
            #if DEBUG
                    Console.Error.WriteLine("pj_transform(): source projection not invertable");
            #endif

                    return -17;
                }

                for(int i=0; i<point_count; i++)
                {
                    XY projected_loc;
                    LP geodetic_loc;

                    projected_loc.x=x[point_offset*i];
                    projected_loc.y=y[point_offset*i];

                    if(projected_loc.x==Libc.HUGE_VAL) continue;

                    geodetic_loc=pj_inv(projected_loc, srcdefn);
                    if(srcdefn.ctx.last_errno!=0)
                    {
                        if((srcdefn.ctx.last_errno!=(int)ERRORNUMBER.EDOM&&srcdefn.ctx.last_errno!=(int)ERRORNUMBER.ERANGE)&&
                            (srcdefn.ctx.last_errno>0||srcdefn.ctx.last_errno<-49||point_count==1||transient_error[-srcdefn.ctx.last_errno]==0))
                            return srcdefn.ctx.last_errno;

                        geodetic_loc.lam=Libc.HUGE_VAL;
                        geodetic_loc.phi=Libc.HUGE_VAL;
                    }

                    x[point_offset*i]=geodetic_loc.lam;
                    y[point_offset*i]=geodetic_loc.phi;
                }
            }

            // --------------------------------------------------------------------
            //		But if they are already lat long, adjust for the prime
            //		meridian if there is one in effect.
            // --------------------------------------------------------------------
            if(srcdefn.from_greenwich!=0.0)
            {
                for(int i=0; i<point_count; i++)
                {
                    if(x[point_offset*i]!=Libc.HUGE_VAL) x[point_offset*i]+=srcdefn.from_greenwich;
                }
            }

            // --------------------------------------------------------------------
            //		Do we need to translate from geoid to ellipsoidal vertical
            //		datum?
            // --------------------------------------------------------------------
            if(srcdefn.has_geoid_vgrids)
            {
                if(Grid.pj_apply_vgridshift(srcdefn, "geoidgrids", ref srcdefn.vgridlist_geoid, ref srcdefn.vgridlist_geoid_count, false, point_count, point_offset, x, y, z)!=0)
                    return pj_ctx_get_errno(srcdefn.ctx);
            }

            // --------------------------------------------------------------------
            //		Convert datums if needed, and possible.
            // --------------------------------------------------------------------
            if(pj_datum_transform(srcdefn, dstdefn, point_count, point_offset, x, y, z)!=0)
            {
                if(srcdefn.ctx.last_errno!=0) return srcdefn.ctx.last_errno;
                else return dstdefn.ctx.last_errno;
            }

            // --------------------------------------------------------------------
            //		Do we need to translate from geoid to ellipsoidal vertical
            //		datum?
            // --------------------------------------------------------------------
            if(dstdefn.has_geoid_vgrids)
            {
                if(Grid.pj_apply_vgridshift(dstdefn, "geoidgrids", ref dstdefn.vgridlist_geoid, ref dstdefn.vgridlist_geoid_count, true, point_count, point_offset, x, y, z)!=0)
                    return dstdefn.ctx.last_errno;
            }

            // --------------------------------------------------------------------
            //		But if they are staying lat long, adjust for the prime
            //		meridian if there is one in effect.
            // --------------------------------------------------------------------
            if(dstdefn.from_greenwich!=0.0)
            {
                for(int i=0; i<point_count; i++)
                {
                    if(x[point_offset*i]!=Libc.HUGE_VAL)
                        x[point_offset*i]-=dstdefn.from_greenwich;
                }
            }

            // --------------------------------------------------------------------
            //		Transform destination latlong to geocentric if required.
            // --------------------------------------------------------------------
            if(dstdefn.is_geocent)
            {
                if(z==null)
                {
                    pj_ctx_set_errno(dstdefn.ctx, (int)PJD_ERR.GEOCENTRIC);
                    return (int)PJD_ERR.GEOCENTRIC;
                }

                pj_geodetic_to_geocentric(dstdefn.a_orig, dstdefn.es_orig, point_count, point_offset, x, y, z);

                if(dstdefn.fr_meter!=1.0)
                {
                    for(int i=0; i<point_count; i++)
                    {
                        if(x[point_offset*i]!=Libc.HUGE_VAL)
                        {
                            x[point_offset*i]*=dstdefn.fr_meter;
                            y[point_offset*i]*=dstdefn.fr_meter;
                        }
                    }
                }
            }
            // --------------------------------------------------------------------
            //		Transform destination points to projection coordinates, if
            //		desired.
            // --------------------------------------------------------------------
            else if(!dstdefn.is_latlong)
            {
                for(int i=0; i<point_count; i++)
                {
                    XY projected_loc;
                    LP geodetic_loc;

                    geodetic_loc.lam=x[point_offset*i];
                    geodetic_loc.phi=y[point_offset*i];

                    if(geodetic_loc.lam==Libc.HUGE_VAL) continue;

                    projected_loc=pj_fwd(geodetic_loc, dstdefn);
                    if(dstdefn.ctx.last_errno!=0)
                    {
                        if((dstdefn.ctx.last_errno!=(int)ERRORNUMBER.EDOM&&dstdefn.ctx.last_errno!=(int)ERRORNUMBER.ERANGE)&&
                            (dstdefn.ctx.last_errno>0||dstdefn.ctx.last_errno<-49||point_count==1||transient_error[-dstdefn.ctx.last_errno]==0))
                            return dstdefn.ctx.last_errno;

                        projected_loc.x=Libc.HUGE_VAL;
                        projected_loc.y=Libc.HUGE_VAL;

                    }

                    x[point_offset*i]=projected_loc.x;
                    y[point_offset*i]=projected_loc.y;
                }
            }

            // --------------------------------------------------------------------
            //		If a wrapping center other than 0 is provided, rewrap around
            //		the suggested center (for latlong coordinate systems only).
            // --------------------------------------------------------------------
            else if(dstdefn.is_latlong&&dstdefn.is_long_wrap_set)
            {
                for(int i=0; i<point_count; i++)
                {
                    if(x[point_offset*i]==Libc.HUGE_VAL) continue;

                    while(x[point_offset*i]<dstdefn.long_wrap_center-PI) x[point_offset*i]+=TWOPI;
                    while(x[point_offset*i]>dstdefn.long_wrap_center+PI) x[point_offset*i]-=TWOPI;
                }
            }

            // --------------------------------------------------------------------
            //		Transform Z from meters if needed.
            // --------------------------------------------------------------------
            if(dstdefn.vto_meter!=1.0&&z!=null)
            {
                for(int i=0; i<point_count; i++) z[point_offset*i]*=dstdefn.vfr_meter;
            }

            // --------------------------------------------------------------------
            //		Transform normalized axes into unusual output coordinate axis
            //		orientation if needed.
            // --------------------------------------------------------------------
            if(dstdefn.axis!="enu")
            {

                int err=pj_adjust_axis(dstdefn.ctx, dstdefn.axis, true, point_count, point_offset, x, y, z);
                if(err!=0) return err;
            }

            return 0;
        }
示例#29
0
 //**********************************************************************
 //						pj_get_spheroid_defn()
 //
 //		Fetch the internal definition of the spheroid. Note that
 //		you can compute "b" from eccentricity_squared as:
 //
 //		b=a*sqrt(1-es)
 //**********************************************************************
 public static void pj_get_spheroid_defn(PJ defn, out double major_axis, out double eccentricity_squared)
 {
     major_axis           = defn.a;
     eccentricity_squared = defn.es;
 }
示例#30
0
        //**********************************************************************
        //                        pj_geocentic_to_wgs84()
        //**********************************************************************
        static int pj_geocentric_to_wgs84(PJ defn, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if(defn.datum_type==PJD._3PARAM)
            {
                for(int i=0; i<point_count; i++)
                {
                    int io=i*point_offset;

                    if(x[io]==Libc.HUGE_VAL) continue;

                    x[io]=x[io]+defn.datum_params[0];
                    y[io]=y[io]+defn.datum_params[1];
                    z[io]=z[io]+defn.datum_params[2];
                }
            }
            else if(defn.datum_type==PJD._7PARAM)
            {
                for(int i=0; i<point_count; i++)
                {
                    int io=i*point_offset;
                    double x_out, y_out, z_out;

                    if(x[io]==Libc.HUGE_VAL) continue;

                    x_out=defn.datum_params[6]*(x[io]-defn.datum_params[5]*y[io]+defn.datum_params[4]*z[io])+defn.datum_params[0];
                    y_out=defn.datum_params[6]*(defn.datum_params[5]*x[io]+y[io]-defn.datum_params[3]*z[io])+defn.datum_params[1];
                    z_out=defn.datum_params[6]*(-defn.datum_params[4]*x[io]+defn.datum_params[3]*y[io]+z[io])+defn.datum_params[2];

                    x[io]=x_out;
                    y[io]=y_out;
                    z[io]=z_out;
                }
            }

            return 0;
        }
示例#31
0
        public static PJ pj_init_ctx(projCtx ctx, string[] argv)
        {
            ctx.last_errno = 0;

            if (argv.Length <= 0)
            {
                pj_ctx_set_errno(ctx, -1); return(null);
            }

            List <string> start = new List <string>();

            Libc.errno = pj_errno = 0;

            // put arguments into internal linked list
            for (int a = 0; a < argv.Length; a++)
            {
                string curr = pj_mkparam(argv[a]);
                if (curr == null)
                {
                    pj_ctx_set_errno(ctx, Libc.errno); return(null);
                }
                start.Add(curr);
            }

            // check if +init present
            if (pj_param_t(ctx, start, "init"))
            {
                bool   found_def;
                string curr = get_init(ctx, start, pj_param_s(ctx, start, "init"), out found_def);
                if (curr == null || !found_def)
                {
                    if (pj_errno != 0 || Libc.errno != 0)
                    {
                        if (pj_errno == 0)
                        {
                            pj_ctx_set_errno(ctx, Libc.errno);
                        }
                    }
                    else
                    {
                        pj_ctx_set_errno(ctx, -2);
                    }

                    return(null);
                }
            }

            // find projection selection
            string name = pj_param_s(ctx, start, "proj");

            if (name == "")
            {
                pj_ctx_set_errno(ctx, -4); return(null);
            }

            // set defaults, unless inhibited
            if (!pj_param_b(ctx, start, "no_defs"))
            {
                get_defaults(ctx, start, name);
            }

            // allocate projection structure
            PJ PIN = GetPJ(name);

            if (PIN == null)
            {
                pj_ctx_set_errno(ctx, -5); return(null);
            }
            PIN.ctx              = ctx;
            PIN.parameters       = start;
            PIN.is_latlong       = false;
            PIN.is_geocent       = false;
            PIN.is_long_wrap_set = false;
            PIN.long_wrap_center = 0.0;
            PIN.axis             = "enu";

            PIN.gridlist        = null;
            PIN.vgridlist_geoid = null;

            // set datum parameters
            if (pj_datum_set(ctx, start, PIN))
            {
                return(null);
            }

            // set ellipsoid/sphere parameters
            if (pj_ell_set(ctx, start, out PIN.a, out PIN.es))
            {
                return(null);
            }

            PIN.a_orig  = PIN.a;
            PIN.es_orig = PIN.es;

            PIN.e      = Math.Sqrt(PIN.es);
            PIN.ra     = 1.0 / PIN.a;
            PIN.one_es = 1.0 - PIN.es;
            if (PIN.one_es == 0.0)
            {
                pj_ctx_set_errno(ctx, -6); return(null);
            }
            PIN.rone_es = 1.0 / PIN.one_es;

            // Now that we have ellipse information check for WGS84 datum
            if (PIN.datum_type == PJD._3PARAM && PIN.datum_params[0] == 0.0 && PIN.datum_params[1] == 0.0 && PIN.datum_params[2] == 0.0 &&
                PIN.a == 6378137.0 && Math.Abs(PIN.es - 0.006694379990) < 0.000000000050)
            {
                PIN.datum_type = PJD.WGS84;                                                                                 //WGS84/GRS80
            }
            // set PIN.geoc coordinate system
            PIN.geoc = PIN.es != 0.0 && pj_param_b(ctx, start, "geoc");

            // over-ranging flag
            PIN.over = pj_param_b(ctx, start, "over");

            // vertical datum geoid grids
            PIN.has_geoid_vgrids = pj_param_t(ctx, start, "geoidgrids");
            if (PIN.has_geoid_vgrids)            // we need to mark it as used.
            {
                pj_param_s(ctx, start, "geoidgrids");
            }

            // longitude center for wrapping
            PIN.is_long_wrap_set = pj_param_b(ctx, start, "lon_wrap");
            if (PIN.is_long_wrap_set)
            {
                PIN.long_wrap_center = pj_param_r(ctx, start, "lon_wrap");
            }

            // axis orientation
            string axis_arg = pj_param_s(ctx, start, "axis");

            if (axis_arg != null && axis_arg.Length != 0)
            {
                string axis_legal = "ewnsud";
                if (axis_arg.Length != 3)
                {
                    pj_ctx_set_errno(ctx, (int)PJD_ERR.AXIS);
                    return(null);
                }

                if (axis_legal.IndexOf(axis_arg[0]) == -1 || axis_legal.IndexOf(axis_arg[1]) == -1 || (axis_arg.Length >= 3 && axis_legal.IndexOf(axis_arg[2]) == -1))
                {
                    pj_ctx_set_errno(ctx, (int)PJD_ERR.AXIS);
                    return(null);
                }

                // it would be nice to validate we don't have on axis repeated
                PIN.axis = axis_arg;
            }

            // central meridian
            PIN.lam0 = pj_param_r(ctx, start, "lon_0");

            // central latitude
            PIN.phi0 = pj_param_r(ctx, start, "lat_0");

            // false easting and northing
            PIN.x0 = pj_param_d(ctx, start, "x_0");
            PIN.y0 = pj_param_d(ctx, start, "y_0");

            // general scaling factor
            if (pj_param_t(ctx, start, "k_0"))
            {
                PIN.k0 = pj_param_d(ctx, start, "k_0");
            }
            else if (pj_param_t(ctx, start, "k"))
            {
                PIN.k0 = pj_param_d(ctx, start, "k");
            }
            else
            {
                PIN.k0 = 1.0;
            }

            if (PIN.k0 <= 0.0)
            {
                pj_ctx_set_errno(ctx, -31); return(null);
            }

            // set units
            double to_meter = double.NaN;

            name = pj_param_s(ctx, start, "units");
            if (name != "")
            {
                to_meter = GetUnitFactor(name);
                if (double.IsNaN(to_meter))
                {
                    pj_ctx_set_errno(ctx, -7); return(null);
                }
                PIN.to_meter = to_meter;
            }

            if (double.IsNaN(to_meter))
            {
                string s = pj_param_s(ctx, start, "to_meter");
                if (s != "")
                {
                    PIN.to_meter = Libc.strtod(s, out s);
                    if (s.Length > 0 && s[0] == '/')
                    {
                        PIN.to_meter /= Libc.strtod(s.Substring(1), out s);                                         // ratio number
                    }
                    PIN.fr_meter = 1.0 / PIN.to_meter;
                }
                else
                {
                    PIN.to_meter = PIN.fr_meter = 1.0;
                }
            }
            else
            {
                PIN.fr_meter = 1.0 / PIN.to_meter;
            }

            // set vertical units
            double vto_meter = double.NaN;

            name = pj_param_s(ctx, start, "vunits");
            if (name != "")
            {
                vto_meter = GetUnitFactor(name);
                if (double.IsNaN(vto_meter))
                {
                    pj_ctx_set_errno(ctx, -7); return(null);
                }
                PIN.vto_meter = vto_meter;
            }

            if (double.IsNaN(vto_meter))
            {
                string s = pj_param_s(ctx, start, "vto_meter");
                if (s != "")
                {
                    PIN.vto_meter = Libc.strtod(s, out s);
                    if (s.Length > 0 && s[0] == '/')
                    {
                        PIN.vto_meter /= Libc.strtod(s.Substring(1), out s);                                         // ratio number
                    }
                    PIN.vfr_meter = 1.0 / PIN.vto_meter;
                }
                else
                {
                    PIN.vto_meter = PIN.to_meter;
                    PIN.vfr_meter = PIN.fr_meter;
                }
            }
            else
            {
                PIN.vfr_meter = 1.0 / PIN.vto_meter;
            }

            // prime meridian
            name = pj_param_s(ctx, start, "pm");
            if (name != "")
            {
                string value = GetPrimeMeridian(name);

                string next_str;
                if (value == null)
                {
                    double tmp = dmstor_ctx(ctx, name, out next_str);
                    if ((tmp != 0.0 || name[0] == '0') && next_str == "")
                    {
                        value = name;
                    }
                }

                if (value == null)
                {
                    pj_ctx_set_errno(ctx, -46); return(null);
                }
                PIN.from_greenwich = dmstor_ctx(ctx, value, out next_str);
            }
            else
            {
                PIN.from_greenwich = 0.0;
            }

            // projection specific initialization
            PIN = PIN.Init();
            if (PIN == null || ctx.last_errno != 0)
            {
                // cleanup error return
                return(null);
            }

            return(PIN);
        }