int gctpc_get_latlon(unsigned char **sec, double **lon, double **lat) { int gdt; unsigned char *gds; double r_maj; /* major axis */ double r_min; /* minor axis */ double lat1; /* first standard parallel */ double lat2; /* second standard parallel */ double c_lon; /* center longitude */ double c_lat; /* center latitude */ double false_east; /* x offset in meters */ double false_north; double dx, dy; double x0, y0; long int (*inv_fn)(); double *llat, *llon, rlon, rlat; int i, nnx, nny, nres, nscan; unsigned int nnpnts; long long_i; gdt = code_table_3_1(sec); gds = sec[3]; /* only process certain grids */ if (gdt != 10 && gdt != 20 && gdt != 30 && gdt != 31) return 1; get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan); /* potentially staggered */ if (nnx < 1 || nny < 1) return 1; llat = *lat; llon = *lon; if (llat != NULL) { free(llat); free(llon); *lat = *lon = llat = llon = NULL; } inv_fn = NULL; dx = dy = 0.0; if (gdt == 10) { // mercator /* get earth axis */ axes_earth(sec, &r_maj, &r_min); dy = GDS_Mercator_dy(gds); dx = GDS_Mercator_dx(gds); /* central point */ c_lon = GDS_Mercator_ori_angle(gds) * (M_PI/180.0); c_lat = GDS_Mercator_latD(gds) * (M_PI/180.0); /* find the eastling and northing of of the 1st grid point */ false_east = false_north = 0.0; long_i = merforint(r_maj,r_min,c_lon,c_lat,false_east,false_north); rlon = GDS_Mercator_lon1(gds) * (M_PI/180.0); rlat = GDS_Mercator_lat1(gds) * (M_PI/180.0); long_i = merfor(rlon, rlat, &x0, &y0); /* initialize for 1st grid point */ x0 = -x0; y0 = -y0; long_i = merinvint(r_maj,r_min,c_lon,c_lat,x0,y0); inv_fn = &merinv; } else if (gdt == 20) { // polar stereographic /* get earth axis */ axes_earth(sec, &r_maj, &r_min); dy = GDS_Polar_dy(gds); dx = GDS_Polar_dx(gds); /* central point */ c_lon = GDS_Polar_lov(gds) * (M_PI/180.0); c_lat = GDS_Polar_lad(gds) * (M_PI/180.0); /* find the eastling and northing of of the 1st grid point */ false_east = false_north = 0.0; long_i = psforint(r_maj,r_min,c_lon,c_lat,false_east,false_north); rlon = GDS_Polar_lon1(gds) * (M_PI/180.0); rlat = GDS_Polar_lat1(gds) * (M_PI/180.0); long_i = psfor(rlon, rlat, &x0, &y0); /* initialize for 1st grid point */ x0 = -x0; y0 = -y0; long_i = psinvint(r_maj,r_min,c_lon,c_lat,x0,y0); inv_fn = &psinv; } else if (gdt == 30) { // lambert conformal conic /* get earth axis */ axes_earth(sec, &r_maj, &r_min); dy = GDS_Lambert_dy(gds); dx = GDS_Lambert_dx(gds); //printf(">>> gctpc dx %lf, dy %lf\n", dx, dy); /* latitudes of tangent/intersection */ lat1 = GDS_Lambert_Latin1(gds) * (M_PI/180.0); lat2 = GDS_Lambert_Latin2(gds) * (M_PI/180.0); /* central point */ c_lon = GDS_Lambert_Lov(gds) * (M_PI/180.0); c_lat = GDS_Lambert_LatD(gds) * (M_PI/180.0); /* find the eastling and northing of of the 1st grid point */ false_east = false_north = 0.0; long_i = lamccforint(r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north); rlon = GDS_Lambert_Lo1(gds) * (M_PI/180.0); rlat = GDS_Lambert_La1(gds) * (M_PI/180.0); long_i = lamccfor(rlon, rlat, &x0, &y0); /* initialize for 1st grid point */ x0 = -x0; y0 = -y0; long_i = lamccinvint(r_maj,r_min,lat1,lat2,c_lon,c_lat,x0,y0); inv_fn = &lamccinv; } else if (gdt == 31) { // albers equal area /* get earth axis */ axes_earth(sec, &r_maj, &r_min); dy = GDS_Albers_dy(gds); dx = GDS_Albers_dx(gds); /* latitudes of tangent/intersection */ lat1 = GDS_Albers_Latin1(gds) * (M_PI/180.0); lat2 = GDS_Albers_Latin2(gds) * (M_PI/180.0); /* central point */ c_lon = GDS_Albers_Lov(gds) * (M_PI/180.0); c_lat = GDS_Albers_LatD(gds) * (M_PI/180.0); /* find the eastling and northing of of the 1st grid point */ false_east = false_north = 0.0; long_i = alberforint(r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north); rlon = GDS_Albers_Lo1(gds) * (M_PI/180.0); rlat = GDS_Albers_La1(gds) * (M_PI/180.0); long_i = alberfor(rlon, rlat, &x0, &y0); /* initialize for 1st grid point */ x0 = -x0; y0 = -y0; long_i = alberinvint(r_maj,r_min,lat1,lat2,c_lon,c_lat,x0,y0); inv_fn = &alberinv; } if (inv_fn == NULL) return 1; if ((*lat = llat = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("gctpc_get_latlon memory allocation failed",""); } if ((*lon = llon = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("gctpc_get_latlon memory allocation failed",""); } /* put x[] and y[] values in lon and lat */ if (stagger(sec, nnpnts, llon, llat)) fatal_error("gctpc: stagger problem",""); printf(">> stagger gctpc x00 %lf y00 %lf\n",llon[0], llat[0]); #pragma omp parallel for schedule(static) private(i) for (i = 0; i < nnpnts; i++) { inv_fn(llon[i]*dx, llat[i]*dy, llon+i, llat+i); llat[i] *= (180.0 / M_PI); llon[i] *= (180.0 / M_PI); if (llon[i] < 0.0) llon[i] += 360.0; } return 0; }
int proj4_initialize(unsigned char **sec, struct proj4_struct *projection) { unsigned int gdt; unsigned char *gds; int has_np; double r_maj, r_min, c_lon, c_lat, x_0, y_0, lat1, lon1; double latsp1, latsp2; char proj4_def[1000]; gdt = code_table_3_1(sec); gds = sec[3]; axes_earth(sec, &r_maj, &r_min); projection->radius_minor = r_min; projection->radius_minor = r_min; if (gdt == 0) { projection->proj_is_nop = 1; projection->x_0 = projection->y_0 = projection->lat_0 = projection->lon_0 = 0.0; return 0; } projection->proj_is_nop = 0; sprintf(proj4_def,"+proj=latlong +a=%lf +b=%lf",r_maj, r_min); if ( (projection->pj_latlon = pj_init_plus(proj4_def)) == NULL) fatal_error("proj4_initialize: pj_init_plus %s failed", proj4_def); if (gdt == 10 && (GDS_Mercator_ori_angle(gds) == 0.0) ) { // mercator no rotation /* central point */ c_lon = 0.0; c_lat = GDS_Mercator_latD(gds); sprintf(proj4_def,"+proj=merc +lat_ts=%lf +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +a=%lf +b=%lf", c_lat, r_maj, r_min); if ((projection->pj_grid = pj_init_plus(proj4_def)) == NULL) fatal_error("proj4_initialize: pj_init_plus %s failed", proj4_def); /* longitude, latitude of first grid point */ projection->lat_0 = lat1 = GDS_Mercator_lat1(gds); projection->lon_0 = lon1 = GDS_Mercator_lon1(gds); x_0 = lon1 * DEG_TO_RAD; y_0 = lat1 * DEG_TO_RAD; if ( pj_transform(projection->pj_latlon, projection->pj_grid, 1, 1, &x_0, &y_0, NULL) != 0 ) fatal_error("proj4_initialize: Proj4 transform to lat-lon",""); projection->x_0 = x_0; projection->y_0 = y_0; } else if (gdt == 20) { // polar stereographic /* central point */ c_lon = GDS_Polar_lov(gds); c_lat = GDS_Polar_lad(gds); /* strange but np/sp flag is used by proj4 but not gctpc */ has_np = ((flag_table_3_5(sec) & 128) == 0); sprintf(proj4_def,"+proj=stere +lat_ts=%lf +lat_0=%s +lon_0=%lf +k_0=1 +x_0=0 +y_0=0 +a=%lf +b=%lf", c_lat, has_np ? "90" : "-90", c_lon, r_maj,r_min); if ((projection->pj_grid = pj_init_plus(proj4_def)) == NULL) fatal_error("Proj4: pj_init_plus %s failed", proj4_def); /* longitude, latitude of first grid point */ projection->lon_0 = lon1 = GDS_Polar_lon1(gds); projection->lat_0 = lat1 = GDS_Polar_lat1(gds); x_0 = lon1 * DEG_TO_RAD; y_0 = lat1 * DEG_TO_RAD; if ( pj_transform(projection->pj_latlon, projection->pj_grid, 1, 1, &x_0, &y_0, NULL) != 0 ) fatal_error("proj4_init: Proj4 transform to lat-lon",""); projection->x_0 = x_0; projection->y_0 = y_0; } else if (gdt == 30) { // lambert conformal conic /* latitudes of tangent/intersection */ latsp1 = GDS_Lambert_Latin1(gds); latsp2 = GDS_Lambert_Latin2(gds); /* central point */ c_lon = GDS_Lambert_Lov(gds); c_lat = GDS_Lambert_LatD(gds); sprintf(proj4_def,"+proj=lcc +lon_0=%lf +lat_0=%lf +lat_1=%lf +lat_2=%lf +a=%lf +b=%lf",c_lon, c_lat,latsp1,latsp2,r_maj,r_min); if ((projection->pj_grid = pj_init_plus(proj4_def)) == NULL) fatal_error("Proj4: pj_init_plus %s failed", proj4_def); /* longitude, latitude of first grid point */ lon1 = GDS_Lambert_Lo1(gds); lat1 = GDS_Lambert_La1(gds); x_0 = lon1 * DEG_TO_RAD; y_0 = lat1 * DEG_TO_RAD; /* longitude, latitude of first grid point */ projection->lon_0 = lon1 = GDS_Lambert_Lo1(gds); projection->lat_0 = lat1 = GDS_Lambert_La1(gds); x_0 = lon1 * DEG_TO_RAD; y_0 = lat1 * DEG_TO_RAD; if ( pj_transform(projection->pj_latlon, projection->pj_grid, 1, 1, &x_0, &y_0, NULL) != 0 ) fatal_error("proj4_init: Proj4 transform to lat-lon",""); projection->x_0 = x_0; projection->y_0 = y_0; } else { return 1; } return 0; }
int polar2ll(unsigned char **sec, double **llat, double **llon) { double *lat, *lon; unsigned char *gds; double dx, dy, orient, de, de2, dr, tmp, xp, yp, h, lat1, lon1, dr2; double di, dj, LatD; int ix, iy; int nnx, nny, nres, nscan; unsigned int nnpnts; get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan); gds = sec[3]; if (nnx == -1 || nny == -1) { fprintf(stderr,"Sorry code does not handle variable nx/ny yet\n"); return 0; } if ((*llat = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("polar2ll memory allocation failed",""); } if ((*llon = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("polar2ll memory allocation failed",""); } lat = *llat; lon = *llon; /* based on iplib */ lat1 = GDS_Polar_lat1(gds) * (M_PI/180); lon1 = GDS_Polar_lon1(gds); orient = GDS_Polar_lov(gds); LatD = GDS_Polar_lad(gds); lon1 *= (M_PI/180.0); orient *= (M_PI/180.0); dy = GDS_Polar_dy(gds); dx = GDS_Polar_dx(gds); h = 1.0; if (GDS_Polar_sps(gds)) { h = -1.0; /* added 12/19/2008 WNE sps checkout */ orient -= M_PI; } // removed 12/11 if (! (GDS_Scan_x(nscan))) dx = -dx; // removed 12/11 if (! (GDS_Scan_y(nscan))) dy = -dy; /* 60 probably becomes something else in grib2 */ /* vsm: from comment to grib2 polar template: "Grid length is in units of 10-3 m at the latitude specified by LaD" do use GDS_Polar_lad(gds) instead of 60? Do use fabs for southern hemisphere? */ de = (1.0 + sin(fabs(LatD)*(M_PI/180.0))) * radius_earth(sec); dr = de * cos(lat1) / (1 + h*sin(lat1)); xp=-h*sin(lon1-orient)*dr/dx; yp= cos(lon1-orient)*dr/dy; // added 12/11 if (! (GDS_Scan_y(nscan))) { yp = yp - nny + 1; } if (! (GDS_Scan_x(nscan))) { xp = xp - nnx + 1; } de2 = de*de; #pragma omp parallel for private(iy,ix,di,dj,dr2,tmp) for (iy = 0; iy < nny; iy++) { for (ix = 0; ix < nnx; ix++) { di = (ix - xp) * dx; dj = (iy - yp) * dy; dr2 = di*di + dj*dj; if (dr2 < de2*1e-6) { lon[ix+iy*nx] = 0.0; lat[ix+iy*nx] = h*90.0; } else { tmp = (orient+h*atan2(di,-dj))*(180.0/M_PI); if (tmp < 0.0) tmp += 360.0; if (tmp > 360.0) tmp -= 360.0; lon[ix+iy*nx] = tmp; lat[ix+iy*nx] = h*asin((de2-dr2)/(de2+dr2))*(180.0/M_PI); } } } return 0; }