int cyclic(unsigned char **sec) { int grid_template, nx, ny, res, scan, flag_3_3, no_dx, basic_ang, sub_ang; unsigned int npnts; unsigned char *gds; double dlon, units; get_nxny(sec, &nx, &ny, &npnts, &res, &scan); if ((unsigned) (nx * ny) != npnts) return 0; if (nx <= 0 || ny <= 0) return 0; grid_template = code_table_3_1(sec); gds = sec[3]; flag_3_3 = flag_table_3_3(sec); no_dx = 0; if (flag_3_3 != -1) { if ((flag_3_3 & 0x20) == 0) no_dx = 1; } if (grid_template == 0) { basic_ang = GDS_LatLon_basic_ang(gds); sub_ang = GDS_LatLon_sub_ang(gds); units = basic_ang == 0 ? 0.000001 : (double) basic_ang / (double) sub_ang; dlon = units * GDS_LatLon_dlon(gds); if (no_dx) dlon = 0.0; dlon = nx * dlon; return (fabs(dlon-360.0) < ERROR); } if (grid_template == 10) { dlon = GDS_Mercator_dx(gds); if (no_dx) dlon = 0.0; dlon = nx * dlon; return (fabs(dlon-360.0) < ERROR); } // need to add gaussian grid - a bit more complicated return 0; }
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 mercator2ll(unsigned char **sec, double **lat, double **lon) { double dx, dy, lat1, lat2, lon1, lon2; double *llat, *llon; int i, j; unsigned int k; double dlon, circum; double n,s,e,w,tmp,error; unsigned char *gds; int nnx, nny, nres, nscan; unsigned int nnpnts; get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan); gds = sec[3]; dy = GDS_Mercator_dy(gds); dx = GDS_Mercator_dx(gds); lat1 = GDS_Mercator_lat1(gds); lat2 = GDS_Mercator_lat2(gds); lon1 = GDS_Mercator_lon1(gds); lon2 = GDS_Mercator_lon2(gds); if (lon1 < 0.0 || lon2 < 0.0 || lon1 > 360.0 || lon2 > 360.0) fatal_error("BAD GDS lon",""); if (lat1 < -90.0 || lat2 < -90.0 || lat1 > 90.0 || lat2 > 90.0) fatal_error("BAD GDS lat",""); if (GDS_Mercator_ori_angle(gds) != 0.0) { fprintf(stderr,"cannot handle non-zero mercator orientation angle %f\n", GDS_Mercator_ori_angle(gds)); return 0; } if (nnx == -1 || nny == -1) { fprintf(stderr,"Sorry geo/mercator code does not handle variable nx/ny yet\n"); return 0; } if ((*lat = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("mercator2ll memory allocation failed",""); } if ((*lon = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("mercator2ll memory allocation failed",""); } /* now figure out the grid coordinates mucho silly grib specification */ /* find S and N latitude */ if (GDS_Scan_y(nscan)) { s = lat1; n = lat2; } else { s = lat2; n = lat1; } if (s > n) fatal_error("Mercator grid: lat1 and lat2",""); /* find W and E longitude */ if ( ((nscan & 16) == 16) && (nny % 2 == 0) && ((nres & 32) == 0) ) { fatal_error("grib GDS ambiguity",""); } if ( ((nscan & 16) == 16) && (nny % 2 == 0) ) { fatal_error("more code needed to decode GDS",""); } if (GDS_Scan_x(nscan)) { w = lon1; e = lon2; } else { w = lon2; e = lon1; } if (e <= w) e += 360.0; llat = *lat; llon = *lon; dlon = (e-w) / (nnx-1); circum = 2.0 * M_PI * radius_earth(sec) * cos(GDS_Mercator_latD(gds) * (M_PI/180.0)); dx = dx * 360.0 / circum; // dlon should be almost == to dx // replace dx by dlon to get end points to match if (dx != 0.0) { error = fabs(dx-dlon) / fabs(dx); if (error >= 0.001) { fprintf(stderr, "\n*** Mercator grid error: inconsistent d-longitude, radius and grid domain\n" "*** d-longitude from grid domain %lf (used), d-longitude from dx %lf (not used)\n", dlon, dx); } dx = dlon; } s = log(tan((45+s/2)*M_PI/180)); n = log(tan((45+n/2)*M_PI/180)); dy = (n - s) / (nny - 1); for (j = 0; j < nny; j++) { tmp = (atan(exp(s+j*dy))*180/M_PI-45)*2; for (i = 0; i < nnx; i++) { *llat++ = tmp; } } for (j = 0; j < nnx; j++) { llon[j] = w + j*dx >= 360.0 ? w + j*dx - 360.0 : w + j*dx; } for (k = nnx; k < nnpnts; k++) { llon[k] = llon[k-nnx]; } return 0; } /* end mercator2ll() */