#include #include #include #include "grb2.h" #include "wgrib2.h" #include "fnlist.h" /* * spaceview.c * * 2011-4-11 Public Domain Wesley Ebisuzaki * * this routine assigns lat/lon to the grid points of a space view * perspective grid * * based on algorithms from * * LRIT/HRIT Global Specification, Coordination Group for Meteorological Satellites * Doc No CGMS 03 isssue 2.6 * date 12 August 1999 * * This document assumed certain constants: satellite height * radius (pole/equator) which differed from the values in the grib file * I attempted to replace the constants with the grib-specified values. * * code can be speeded up x=-x and y=-y relationships * * code limited to orient == 0 and sat lat = 0 * v1.0 4-2011 * * 4/2015: L. Majewski fixed defn of lop * 9/2017: W. Ebisuzaki lop does not need to be changed to radians */ #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif #ifndef M_PI_4 #define M_PI_4 0.78539816339744830962 /* pi/4 */ #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #endif extern enum output_order_type output_order; int space_view2ll(unsigned char **sec, double **lat, double **lon) { double major, minor, r_eq, r_pol, sat_height; double lap, lop, orient_angle, angular_size; double xp, yp, dx, dy, rx, ry, x, y; double cos_x, cos_y, sin_x, sin_y; double factor_1, factor_2, tmp1, Sd, Sn, Sxy, S1, S2, S3; int x0, y0, i, ix, iy; double *llat, *llon; double *s_x, *c_x; int nnx, nny, nres, nscan; unsigned int nnpnts; get_nxny(sec, &nnx, &nny, &nnpnts, &nres, &nscan); //fprintf(stderr,"ALPHA: experimental space_view2ll scan=%d\n", nscan >> 4); axes_earth(sec, &major, &minor); //fprintf(stderr,">> axes %lf minor %lf\n", major,minor); r_eq = major * 0.001; r_pol = minor * 0.001; angular_size = 2.0 * asin(1e6/ uint4(sec[3]+68)); sat_height = uint4(sec[3]+68) * 1e-6 * r_eq; //fprintf(stderr,">> sat height %lf\n",sat_height); lap = int4(sec[3]+38); lop = int4(sec[3]+42); /* apply default scaling factor */ lap *= 1e-6; lop *= 1e-6; //fprintf(stderr,">> lap %lf lop %lf degrees\n",lap, lop); if (lap != 0.0) return 0; // need to extend code /* convert to radians */ lap *= (180.0/M_PI); // lop *= (180.0/M_PI); orient_angle = int4(sec[3]+64); /* apply default scaling factor */ orient_angle *= 1e-6; if (orient_angle != 0.0) return 0; // need to extend code xp = int4(sec[3]+55) * 0.001; yp = int4(sec[3]+59) * 0.001; //fprintf(stderr,">> xp %lf yp %lf pixels\n",xp, yp); x0 = int4(sec[3]+72); y0 = int4(sec[3]+76); //fprintf(stderr,">> origin x0 %d yo %d pixels\n",x0, y0); dx = int4(sec[3]+47); dy = int4(sec[3]+51); //fprintf(stderr,">> dia: dx %lf dy %lf pixels\n",dx, dy); rx = angular_size / dx; ry = (r_pol/r_eq) * angular_size / dy; //fprintf(stderr,">> factor %.17lg %.18lg, q: %.18lg %.18lg\n", 256*256.0/(-781648343.0), // 256*256.0/(-781648343.0), rx, ry); if (nnx < 1 || nny < 1 || nnx*nny != nnpnts) { fprintf(stderr,"space_view2ll need rectangular grid\n"); return 0; } if ((*lat = (double *) malloc(sizeof(double) * (size_t) nnpnts)) == NULL) { fatal_error("space_view2ll memory allocation failed",""); } if ((*lon = (double *) malloc(sizeof(double) * (size_t) nnpnts)) == NULL) { fatal_error("space_view2ll memory allocation failed",""); } llat = *lat; llon = *lon; /* find center point in we:sn coordinate */ if (GDS_Scan_x(nscan)) { xp = xp - x0; } else { xp = (nnx-1) - (xp - x0); } if (GDS_Scan_y(nscan)) { yp = yp - y0; } else { yp = (nny-1) - (yp - y0); } //fprintf(stderr,">> new center point point x/y=%lf %lf nnx=%d nny=%d\n", xp,yp,nnx, nny); //fprintf(stderr,">> rx %lf ry %lf\n", rx,ry); i = 0; factor_2 = (r_eq/r_pol)*(r_eq/r_pol); factor_1 = sat_height * sat_height - r_eq * r_eq; //fprintf(stderr," factor_1 %lf factor_2 %lf\n",factor_1,factor_2); s_x = (double *) malloc(sizeof(double) * (size_t) nnx); c_x = (double *) malloc(sizeof(double) * (size_t) nnx); if (s_x == NULL || c_x == NULL) fatal_error("space_view: memory allocation",""); for (ix = 0; ix < nnx; ix++) { x = (ix - xp) * rx; s_x[ix] = sin(x); c_x[ix] = sqrt(1.0 - s_x[ix]*s_x[ix]); } for (iy = 0; iy < nny; iy++) { y = (iy - yp) * ry; sin_y = sin(y); // cos_y = cos(y); cos_y = sqrt(1.0 - sin_y*sin_y); // printf("iy %d y %lf cos %lf sin %lf\n", iy, y, cos_y, sin_y); // old tmp1 = (cos_y*cos_y + factor_2*sin_y*sin_y); tmp1 = (1 + (factor_2-1.0)*sin_y*sin_y); for (ix = 0; ix < nnx; ix++, i++) { x = (ix - xp) * rx; // sin_x = sin(x); //// cos_x = cos(x); // cos_x = sqrt(1.0 - sin_x*sin_x); sin_x = s_x[ix]; cos_x = c_x[ix]; Sd = sat_height * cos_x * cos_y; Sd = Sd * Sd - tmp1*factor_1; if (Sd <= 0.0) { // outside of view llat[i] = llon[i] = UNDEFINED_ANGLE; } else { Sd = sqrt(Sd); Sn = (sat_height*cos_x*cos_y - Sd) / tmp1; S1 = sat_height - Sn * cos_x * cos_y; S2 = Sn * sin_x * cos_y; S3 = Sn * sin_y; Sxy = sqrt(S1*S1 + S2*S2); llon[i] = atan(S2/S1)*(180.0/M_PI) + lop; if (llon[i] > 360.0) llon[i] -= 360.0; // if (llon[i] < 0.0) llon[i] += 360.0; should never happen as lop >= 0 llat[i] = atan(factor_2*S3/Sxy)*(180.0/M_PI); /* if ((iy == 1588 || iy == 300) && ix == 1588) { printf("ix %d iy %d x %lf y %lf\n",ix,iy,x,y); printf("cos_x %lf sin_x %lf\n", cos_x, sin_x); printf("cos_y %lf sin_y %lf\n", cos_y, sin_y); printf("Sd=%lf Sn=%lf S1 %lf S2 %lf S3 %lf\n", Sd, Sn, S1 , S2, S3); printf("Sxy=%lf S3/Sxy=%lf atan() %lf\n", Sxy, S3/Sxy, atan(S3/Sxy)); printf("lat %lf lon %lf i=%d\n", llat[i] , llon[i], i); } */ } } } free(s_x); free(c_x); //fprintf(stderr,">>return\n"); return 0; }