예제 #1
0
파일: geo.c 프로젝트: mmase/wgrib2
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() */ 
예제 #2
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;
}
예제 #3
0
파일: geo.c 프로젝트: mmase/wgrib2
int lambert2ll(unsigned char **sec, double **llat, double **llon) {


    double n;
    double *lat, *lon;

    double dx, dy, lat1r, lon1r, lon2d, lon2r, latin1r, latin2r;
    double lond, latd, d_lon;
    double f, rho, rhoref, theta, startx, starty;
    int j, nnx, nny, nres, nscan;
    double x, y, tmp;
    unsigned char *gds;
    double latDr;
    double earth_radius;
    unsigned int nnpnts;

    get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan);

    if (nnx <= 0 || nny <= 0) {
        fprintf(stderr,"Sorry code does not handle variable nx/ny yet\n");
        return 0;
    }

    earth_radius = radius_earth(sec);
    gds = sec[3];
    dy      = GDS_Lambert_dy(gds);
    dx      = GDS_Lambert_dx(gds);
    lat1r   = GDS_Lambert_La1(gds) * (M_PI / 180.0);
    lon1r   = GDS_Lambert_Lo1(gds) * (M_PI / 180.0);
    lon2d   = GDS_Lambert_Lov(gds);
    lon2r   = lon2d * (M_PI / 180.0);
    latin1r = GDS_Lambert_Latin1(gds) * (M_PI/180.0);
    latin2r = GDS_Lambert_Latin2(gds) * (M_PI/180.0);

//  fix for theta start value crossing 0 longitude
//    if ((lon1r - lon2r) > 0) lon2r = lon2r + 2*M_PI;


//
// Latitude of "false origin" where scales are defined.
// It is used to estimate "reference_R", rhoref.
// Often latDr == latin1r == latin2r and non-modified code is true and works fine.
// But could be different if intersection latitudes latin1r and latin2r are different.
// Usually latDr must be latin1r <=  latDr <= latin2r, other could be strange.
//
    latDr = GDS_Lambert_LatD(gds) * (M_PI/180.0);


    if (lon1r < 0) fatal_error("bad GDS, lon1r < 0.0","");

    if ( fabs(latin1r - latin2r) < 1E-09 ) {
        n = sin(latin1r);
    }
    else {
        n = log(cos(latin1r)/cos(latin2r)) / 
        log(tan(M_PI_4 + latin2r/2.0) / tan(M_PI_4 + latin1r/2.0));
    }
  
    f = (cos(latin1r) * pow(tan(M_PI_4 + latin1r/2.0), n)) / n;
  
    rho = earth_radius * f * pow(tan(M_PI_4 + lat1r/2.0),-n);
    // old rhoref = earth_radius * f * pow(tan(M_PI_4 + latin1r/2.0),-n);
    rhoref = earth_radius * f * pow(tan(M_PI_4 + latDr/2.0),-n);

    // 2/2009 .. new code
    d_lon = lon1r - lon2r;
    if (d_lon > M_PI) d_lon -= 2*M_PI;
    if (d_lon < -M_PI) d_lon += 2*M_PI;
    theta = n * d_lon; 
    // 2/2009 theta = n * (lon1r - lon2r); 

    startx = rho * sin(theta);
    starty = rhoref - rho * cos(theta);

    if ((*llat = (double *) malloc(nnpnts * sizeof(double))) == NULL) {
        fatal_error("lambert2ll memory allocation failed","");
    }
    if ((*llon = (double *) malloc(nnpnts * sizeof(double))) == NULL) {
        fatal_error("lambert2ll memory allocation failed","");
    }
    lat = *llat;
    lon = *llon;

    /* put x[] and y[] values in lon[] and lat[] */
    if (stagger(sec, nnpnts, lon, lat)) fatal_error("geo: stagger problem","");

    dx = fabs(dx);
    dy = fabs(dy);

#pragma omp parallel for private(j,x,y,tmp,theta,rho,lond,latd)
    for (j = 0; j < nnpnts; j++) {
	y = starty + lat[j]*dy;
        x = startx + lon[j]*dx;
	tmp = rhoref - y;
	theta = atan(x / tmp);
        rho = sqrt(x * x + tmp*tmp);
        rho = n > 0 ? rho : -rho;
        lond = lon2d + todegrees(theta/n);
        latd = todegrees(2.0 * atan(pow(earth_radius * f/rho,1.0/n)) - M_PI_2);
	lond = lond >= 360.0 ? lond - 360.0 : lond;
	lond = lond < 0.0 ? lond + 360.0 : lond;
        lon[j] = lond;
        lat[j] = latd;
    }
    return 0;
} /* end lambert2ll() */