/* mktransect.c * * * Emilio 4/1/99 * Updated program. * Emilio 4/21/98 * * * COMPILE AS: gccemu mktransect * RUN AS: mktransect <lon_o>#include "emu.h" const char * cpszUsage = {"usage: mktransect \n\ Create a binary or NC file with containing a transect mask.\n\ \n\ Command-line switches specific to this program are:\n\ \t-xy lon_o lat_o lon_f lat_f \n\ \n\ "}; /* local functions */ void Setup(void); void Process(void); void Output(void); int lonlatToidx(float lon, float lat); void idxTolonlat(int i, float *lon, float *lat); int getNormalidx(char *dir, float normalangle, float delDegdist, float lon, float lat); float distlonlatTokm(float lon1, float lat1, float lon2, float lat2); /* local variables */ float lon_o, lat_o, lon_f, lat_f; WORD *transect; float scale_factor = 0.1; int errnc; int main(int argc, char *argv[]) { AssignString(&pszNCtitle, "Transect Mask"); AssignString(&pszNChist, "transect mask created by mktransect"); Initialize(&argc, argv, NOMASK); Setup(); Process(); Output(); CleanUp(); return(0); } /* ================================================================= */ void Setup(void) { int i; transect = alloc1d_us(0,nRows*nCols-1); for (i = 0; i < nRows*nCols; i++) transect[i] = -999; } /* ================================================================= */ void Process(void) { int i, i_o, i_f, col, row; int bug=0,flag=0; WORD distval, Totpts=0; int col_o, row_o, col_f, row_f; float lon, lat, del_lon; float angle, normalangle, theta, delDegdist, dist, Totdist; i_o = lonlatToidx(lon_o, lat_o); idxTolonlat(i_o, &lon_o, &lat_o); i_f = lonlatToidx(lon_f, lat_f); idxTolonlat(i_f, &lon_f, &lat_f); (void) getRowRevCol(i_o, &col_o, &row_o); (void) getRowRevCol(i_f, &col_f, &row_f); if (bDebug) { printf("HERE:%d, lon_o=%.3f lat_o=%.3f lon_f=%.3f lat_f=%.3f \n", bug++, lon_o,lat_o,lon_f,lat_f); printf("HERE:%d, col_o=%d row_o=%d col_f=%d row_f=%d \n", bug++, col_o,row_o,col_f,row_f); } /* angle is angle from 1st endpoint (_o) to last endpoint (_f), with respect to the "x-axis" (>0 in the increasing-longitude direction); range: -179.999... to 180 */ angle = RAD2DEG * atan2((lat_f - lat_o) , (lon_f - lon_o)); /* normalangle is the angle perpendicular to the vector, in "right-handed" direction */ normalangle = (angle >= -90.0 && angle < -180.0) ? (angle + 270.0) : (angle - 90.0); /* delDegdist: distance step along vector direction; range: fHScale*(1 -> sqrt(2)) */ theta = fabs(fabs(angle) - 90.0); theta = (theta > 45) ? (90.0 - theta) : theta; /* theta: 0->45 deg */ delDegdist = fHScale/cos(theta/RAD2DEG); Totdist = distlonlatTokm(lon_f, lat_f, lon_o, lat_o); /* Put origin value into transect array */ dist = 10.0; /* The origin will be 1 km */ distval = (WORD) floor((double)dist + 0.5); lon = lon_o; lat = lat_o; i = i_o; transect[i] = distval; i = getNormalidx("right", normalangle, delDegdist, lon, lat); transect[i] = distval; i = getNormalidx("left", normalangle, delDegdist, lon, lat); transect[i] = distval; Totpts+=3; if (bDebug) printf("HERE:%d, Totdist=%.3f (0.1km), angle=%.4f, normalangle=%.4f, delDegdist=%.4f, i=%d\n", bug++, Totdist,angle,normalangle,delDegdist,i); while (dist <= (Totdist + 10.0)) { dist += (DEG2KM / scale_factor) * delDegdist; distval = (WORD) floor((double)dist + 0.5); lon += delDegdist * cos(angle/RAD2DEG); lat += delDegdist * sin(angle/RAD2DEG); i = lonlatToidx(lon, lat); (void) getRowRevCol(i, &col, &row); flag++; if (!bQuiet && ((flag % 20) == 0 || flag==1)) printf(" i=%d, lon=%.3f,lat=%.3f, col=%d,row=%d, dist=%.3f \n", i,lon,lat,col,row,dist); transect[i] = distval; i = getNormalidx("right", normalangle, delDegdist, lon, lat); transect[i] = distval; i = getNormalidx("left", normalangle, delDegdist, lon, lat); transect[i] = distval; Totpts+=3; } if (!bQuiet) printf("\n Total Number of Points Selected: %d \n", Totpts); } /* ================================================================= */ /* ==================== WRITE OUT BINARY FILE ====================== */ void Output(void) { FILE *fout; int ncID; /* netCDF file ID */ int tID; /* time axis ID */ int varID; char varName[NAMELEN]; /* Name of NC variable(s) to be written */ char varLongName[NAMELEN]; /* Long Name of NC variable(s) to be written */ if (bOutBinary) /* write output to binary files */ { fout = OUTPUTfile(pszOutputFile, ".bil"); fwrite(transect, sizeof(WORD), nRows*nCols, fout); fclose(fout); } else { /* setup new NC file from NC headers */ SetupDefaultAxes(FALSE, FALSE); ncID = newNCsetup(&tID, pszOutputFile, pszNCtitle, pszNChist); strcpy(varName, "transect"); sprintf(varLongName,"%s mask", varName); /* the NC lib doesn't support unsigned short, that MAY cause a problem */ varID = DefNCvar(ncID, varName, EMU_SHORT, "xy", varLongName, "km"); AddNCCompressionAttributes(ncID, varID, scale_factor, 0.0); errnc = nc_put_var_short(ncID, varID, transect); errnc = nc_close(ncID); } } /* ================================================================= */ void ProcessCommandLineArgs(int * pArgc, char * argv[]) { int i; for (i=1; i<*pArgc; i++) if (strcmp(argv[i], "-xy") == 0) { lon_o = atof(argv[++i]); lat_o = atof(argv[++i]); lon_f = atof(argv[++i]); lat_f = atof(argv[++i]); } } /* ================================================================= */ void LocalCleanUp(void) { free(pszOutputFile); free1d_us(transect,0,nRows*nCols-1); } /* ================================================================= */ /* get the 1-d location index from (lon,lat) */ int lonlatToidx(float lon, float lat) { int row, col; col = (int) floor((double)(lon - fLonLeft)/fHScale); row = (int) floor((double)(fLatTop - lat)/fVScale); return (row*nCols + col); } /* reshift (lon,lat) point to the center of the cell */ void idxTolonlat(int i, float *lon, float *lat) { int row, col; (void) getRowRevCol(i, &col, &row); *lon = fLonLeft + fHScale*((float)col + 0.5); *lat = fLatTop - fVScale*((float)row + 0.5); } int getNormalidx(char *dir, float normalangle, float delDegdist, float lon, float lat) { float lonNorm, latNorm, angle; if (istype(dir, "left")) angle = (normalangle >= 0.0) ? (normalangle-180.0) : (normalangle+180.0); else angle = normalangle; lonNorm = lon + delDegdist * cos(angle/RAD2DEG); latNorm = lat + delDegdist * sin(angle/RAD2DEG); return (lonlatToidx(lonNorm, latNorm)); } float distlonlatTokm(float lon1, float lat1, float lon2, float lat2) { return ((float) sqrt((double)(SQR(lon2 - lon1) + SQR(lat2 - lat1))) * DEG2KM * 10); } * eg, mktransect -70 1 -55 -10 OR mktransect -70 4 -70 -10 ******************************************************************************/