// 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; }
//********************************************************************** // 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); }
// 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); }
// 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; }
}; // 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!"); } }
// 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; }
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!"); } }
//********************************************************************** // 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); }
//********************************************************************** // 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); }
// 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; }
// 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); }
//********************************************************************** // 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); }
//********************************************************************** // 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; }
//********************************************************************** // 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); }
//********************************************************************** // 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)); }
//********************************************************************** // 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); }
//********************************************************************** // 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; }
//********************************************************************** // 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; }
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); }
//********************************************************************** // 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); }
//********************************************************************** // 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; }
//********************************************************************** // 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; }
//********************************************************************** // 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; }
//********************************************************************** // 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; }
//********************************************************************** // 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); }
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; }
//********************************************************************** // 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; }
//********************************************************************** // 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; }
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); }