#include #include #include #include #include "mpp.h" #include "mosaic_util.h" #include "tool_util.h" #include "constant.h" #include "create_hgrid.h" #define D2R (M_PI/180.) #define R2D (180./M_PI) /********************************************************************************* some private routines used in this file *********************************************************************************/ void calc_geocoords_centerpole(int nx, int ny, double *x, double *y); void conformal_map_coords2xyz ( int ni, int nj, double *lx, double *ly, double *X, double *Y, double *Z ); void map_xyz2lonlat(int ni, int nj, double *X, double *Y, double *Z, double *lon, double *lat ); void rotate_about_xaxis(int ni, int nj, double *X, double *Y, double *Z, double angle); void permutiles(int ni, int nj, double *b, int num); void calc_fvgrid(int nx, int ny, int nratio, double *dx, double *dy, double *area); double* angle_between_vectors(int ni, int nj, double *vec1, double *vec2); double* excess_of_quad(int ni, int nj, double *vec1, double *vec2, double *vec3, double *vec4 ); double* plane_normal(int ni, int nj, double *P1, double *P2); void calc_rotation_angle(int nxp, int nyp, double *x, double *y, double *angle_dx, double *angle_dy); /******************************************************************************* void create_conformal_cubic_grid( int *npoints, int *nratio, char *method, char *orientation, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, double *angle_dy ) create cubic grid. All six tiles grid will be generated. *******************************************************************************/ void create_conformal_cubic_grid( int *npts, int *nratio, char *method, char *orientation, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, double *angle_dy ) { int nx, ny, nxp, nyp; nx = *npts; ny = nx; nxp = nx+1; nyp = nxp; /*calculate geographic coordinates. */ if(strcmp(orientation, "center_pole") == 0) calc_geocoords_centerpole(nx, ny, x, y); else mpp_error("create_cubic_grid: only center pole orientation is implemented"); /* calculate cell length and area */ calc_fvgrid(nx, ny, *nratio, dx, dy, area); /*calculate rotation angle, just some workaround, will modify this in the future. */ calc_rotation_angle(nxp, nyp, x, y, angle_dx, angle_dy ); }; /* create_conformal_cubic_grid */ /*********************************************************************** calc_geoocoords_centerpole(int nx, int ny, double *x, double *y); calculate geographic coordinates for all six tiles. ***********************************************************************/ void calc_geocoords_centerpole(int nx, int ny, double *x, double *y) { int i, j, n, m, nxp, nyp, nxh, nyh; double *lx, *ly, *X, *Y, *Z, *lonP, *latP, *lonE, *latE, *tmp; nxp = nx+1; nyp = ny+1; nxh = (nxp+1)/2; nyh = (nyp+1)/2; lx = (double *)malloc(nxh*nyh*sizeof(double)); ly = (double *)malloc(nxh*nyh*sizeof(double)); n = 0; for(j=0; j= M_PI ) lonP[j*nxp+i] -= 2*M_PI; } } tmp = (double *) malloc(nxh*nyh*sizeof(double)); n = 0; for(j=0; j fabs(lx[n]) ) { xc = 1-Y[n]; yc = 1-X[n]; } zc = cpow((xc+I*yc)/2.,4); /*Evaluate the Taylor series. */ w = 0; for(m=order; m>=0; m--) w = ( w + A[m] ) * zc; if( w != 0. ) w = cpow(I,THRD) * cpow( w*I, THRD); w = (w-RA)/(CB+CC*w); X[n] = creal(w); Y[n] = cimag(w); h = 2./(1+cpow(X[n],2)+cpow(Y[n],2)); X[n] = X[n]*h; Y[n] = Y[n]*h; Z[n] = h-1; } for(n=0; n< ni*nj; n++) { if(fabs(ly[n]) > fabs(lx[n]) ) { t = X[n]; X[n] = Y[n]; Y[n] = t; } if(lx[n]<0) X[n] = -X[n]; if(lx[n]==0) X[n] = 0; if(ly[n]<0) Y[n] = -Y[n]; if(ly[n]==0) Y[n] = 0; } }; /* conformal_map_coords2xyz */ /********************************************************** Convert 3-D coordinates (x,y,z) to (lon,lat) Assumes "lat" is positive with "z", equatorial plane falls at z=0 and "lon" is measured anti-clockwise (eastward) from x-axis (y=0) about z-axis. ************************************************************/ void map_xyz2lonlat(int ni, int nj, double *X, double *Y, double *Z, double *lon, double *lat ) { int i, j, n; double req; for(n=0; n=0) lon[n] += M_PI; if(X[n]<=0 && Y[n] < 0) lon[n] -= M_PI; } }; /* map_xyz2lonlat */ /************************************************************** void rotate_about_xaxis(int ni, int nj, double *X, double *Y, double *Z, double angle) Rotate about X axis by "angle" ***************************************************************/ void rotate_about_xaxis(int ni, int nj, double *X, double *Y, double *Z, double angle) { int i, j, n; double s,c,old; const double tolerance = 1.e-9; s=sin(angle); c=cos(angle); if (c0) s = 1; else s = -1; } for(n=0; n1, 4->2, 5->4, 1->5, the tiles 3 and 6 get rotated 90 degs. *************************************************************************/ void permutiles(int ni, int nj, double *b, int num) { int i, j, k, n; int ntiles = 6; double *c=NULL; c = (double *)malloc(ni*nj*ntiles*sizeof(double)); for(k=0; ki) areal[j*(nif-1)+i] = areal[i*(nif-1)+j]; } } /* Use symmetry to fill second octant */ for(j=1; j* angle_between_vectors(array vec1, array vec2) *******************************************************************************/ double* angle_between_vectors(int ni, int nj, double *vec1, double *vec2) { int n; double vector_prod, nrm1, nrm2; double *angle; angle = (double *)malloc(ni*nj*sizeof(double)); for(n=0; n= nxp) { /* find the neighbor tile. */ if(n % 2 == 0) { /* tile 1, 3, 5 */ tp1 = n+1; ip1 = 0; } else { /* tile 2, 4, 6 */ tp1 = n+2; if(tp1 >= ntiles) tp1 -= ntiles; ip1 = ny-j-1; jp1 = 0; } } if(im1 < 0) { /* find the neighbor tile. */ if(n % 2 == 0) { /* tile 1, 3, 5 */ tm1 = n-2; if(tm1 < 0) tm1 += ntiles; jm1 = ny; im1 = nx-j; } else { /* tile 2, 4, 6 */ tm1 = n-1; im1 = nx; } } angle_dx[n*nxp*nyp+j*nxp+i] = atan2(y[tp1*nxp*nyp+jp1*nxp+ip1]-y[tm1*nxp*nyp+jm1*nxp+im1], (x[tp1*nxp*nyp+jp1*nxp+ip1]-x[tm1*nxp*nyp+jm1*nxp+im1])*lon_scale )*R2D; tp1 = n; tm1 = n; ip1 = i; im1 = i; jp1 = j+1; jm1 = j-1; if(jp1 >=nyp) { /* find the neighbor tile. */ if(n % 2 == 0) { /* tile 1, 3, 5 */ tp1 = n+2; if(tp1 >= ntiles) tp1 -= ntiles; jp1 = nx-i; ip1 = 0; } else { /* tile 2, 4, 6 */ tp1 = n+1; if(tp1 >= ntiles) tp1 -= ntiles; jp1 = 0; } } if(jm1 < 0) { /* find the neighbor tile. */ if(n % 2 == 0) { /* tile 1, 3, 5 */ tm1 = n-1; if(tm1 < 0) tm1 += ntiles; jm1 = ny; } else { /* tile 2, 4, 6 */ tm1 = n-2; if(tm1 < 0) tm1 += ntiles; im1 = nx; jm1 = nx-i; } } angle_dy[n*nxp*nyp+j*nxp+i] = atan2(y[tp1*nxp*nyp+jp1*nxp+ip1]-y[tm1*nxp*nyp+jm1*nxp+im1], (x[tp1*nxp*nyp+jp1*nxp+ip1]-x[tm1*nxp*nyp+jm1*nxp+im1])*lon_scale )*R2D; } } } }; /* calc_rotation_angle */