Example #1
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 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;
}
Example #3
0
File: geo.c Project: mmase/wgrib2
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;
}