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, lon1, lon2; get_nxny(sec, &nx, &ny, &npnts, &res, &scan); if (GDS_Scan_staggered(scan)) return 0; if (nx <= 1 || 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 (no_dx) return 0; 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 has to be defined */ dlon = units * GDS_LatLon_dlon(gds); return (fabs(nx*dlon-360.0) < ERROR); } if (grid_template == 10) { if (output_order != wesn) return 0; // only works with we:sn order lon1 = GDS_Mercator_lon1(gds); lon2 = GDS_Mercator_lon2(gds); if (lon2 < lon1) lon2 += 360.0; dlon = (lon2-lon1)*nx/(nx-1.0); return (fabs(dlon-360.0) < ERROR); } if (grid_template == 40) { basic_ang = GDS_Gaussian_basic_ang(gds); sub_ang = GDS_Gaussian_sub_ang(gds); units = basic_ang == 0 ? 0.000001 : (double) basic_ang / (double) sub_ang; /* dlon has to be defined */ dlon = units * GDS_Gaussian_dlon(gds); return (fabs(nx*dlon-360.0) < ERROR); } return 0; }
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 regular2ll(unsigned char **sec, double **lat, double **lon) { int basic_ang, sub_ang; double units, dlat, dlon, lat1, lat2, lon1, lon2; double e, w, n, s, dx, dy; int i, j; double *llat, *llon; unsigned char *gds; int nnx, nny, nres, nscan; unsigned int nnpnts; get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan); gds = sec[3]; if (nny == -1) { fprintf(stderr,"Sorry code does not handle variable ny yet\n"); return 0; } if ((*lat = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("regular2ll memory allocation failed",""); } if ((*lon = (double *) malloc(nnpnts * sizeof(double))) == NULL) { fatal_error("regular2ll memory allocation failed",""); } /* now figure out the grid coordinates mucho silly grib specification */ basic_ang = GDS_LatLon_basic_ang(gds); sub_ang = GDS_LatLon_sub_ang(gds); if (basic_ang != 0) { units = (double) basic_ang / (double) sub_ang; } else { units = 0.000001; } dlat = GDS_LatLon_dlat(gds) * units; dlon = GDS_LatLon_dlon(gds) * units; lat1 = GDS_LatLon_lat1(gds) * units; lat2 = GDS_LatLon_lat2(gds) * units; lon1 = GDS_LatLon_lon1(gds) * units; lon2 = GDS_LatLon_lon2(gds) * units; if (lon1 < 0.0 || lon2 < 0.0) fatal_error("BAD grid definition lon < zero",""); if (lon1 > 360.0 || lon2 > 360.0) fatal_error("BAD grid definition lon >= 360",""); if (lat1 < -90.0 || lat2 < -90.0 || lat1 > 90.0 || lat2 > 90.0) fatal_error("BAD grid definition lat",""); /* find S latitude and dy */ if (GDS_Scan_y(nscan)) { s = lat1; n = lat2; } else { s = lat2; n = lat1; } if (s > n) fatal_error("lat-lon grid: lat1 and lat2 inconsistent with scan order",""); if (nny != 1) { dy = (n - s) / (nny - 1); if (nres & 16) { /* lat increment is valid */ if (fabs(dy - dlat) > 0.001) fatal_error("lat-lon grid: dlat is inconsistent",""); } } else { dy = 0.0; } // fprintf(stderr,">>> geo: dy %lf dlat %lf nres %d has dy %d has dx %d\n", dy, dlat, nres, nres & 16, nres & 32); /* find W latitude and dx */ if ( GDS_Scan_row_rev(nscan) && (nny % 2 == 0) && ((nres & 32) == 0) ) { fatal_error("grib GDS ambiguity",""); } if (GDS_Scan_x(nscan)) { w = lon1; e = lon2; if (GDS_Scan_row_rev(nscan) && ((nres & 32) == 0)) { e = lon1 + (nnx-1) * dlon; } } else { w = lon2; e = lon1; if (GDS_Scan_row_rev(nscan) && ((nres & 32) == 0)) { w = lon1 - (nnx-1) * dlon; } } if (e <= w) e += 360.0; if (e-w > 360.0) e -= 360.0; if (w < 0) { w += 360.0; e += 360.0; } /* lat-lon should be in a WE:SN order */ if (nnx > 0 && nny > 0) { /* non-thinned, potentially staggered grid */ /* put x[] and y[] values in lon[] and lat[] */ llat = *lat; llon = *lon; if (stagger(sec, nnpnts,llon,llat)) fatal_error("geo: stagger problem",""); if (nnx != 1) { dx = (e-w) / (nnx - 1); dx = fabs(dx); if (nres & 32) { /* lon increment is valid */ if (fabs(dx - fabs(dlon)) > 0.001) fatal_error("lat-lon grid: dlon is inconsistent",""); } } else { dx = 0.0; } dy = fabs(dy); #pragma omp parallel for private(j) for (j = 0; j < nnpnts; j++) { llon[j] = lon1 + llon[j]*dx; llon[j] = llon[j] >= 360.0 ? llon[j] - 360.0 : llon[j]; llon[j] = llon[j] < 0.0 ? llon[j] + 360.0 : llon[j]; llat[j] = lat1 + llat[j]*dy; } return 0; } /* must be thinned grid */ llat = *lat; /* quasi-regular grid */ for (j = 0; j < nny; j++) { for (i = 0; i < variable_dim[j]; i++) { *llat++ = s + j*dy; } } llon = *lon; /* quasi-regular grid */ for (j = 0; j < nny; j++) { dx = (e-w) / (variable_dim[j]-1); for (i = 0; i < variable_dim[j]; i++) { *llon++ = w + i*dx >= 360.0 ? w + i*dx - 360.0: w + i*dx; } } return 0; } /* end regular2ll() */