// // Author: Joshua Cohen // Copyright 2016 // // This code is adapted from the original Fortran topozero.f90 code. All relevant or associated // structs/methods are contained in this same src/ folder as well (all adapted from the old // Fortran code). The code was validated in full against the original Fortran code with a // COSMO SkyMed test set and produced the same exact outputs. // // Note: There are a few blocks of code commented out currently (including some variables). These // sections calculate things that will be used in future SWOT processing, but to mildly // reduce runtime and some overhead they will stay commented out until use. // // Note 2: Most include statements in these source files are relatively-pathed. For the most part // the files are in a standard main/src/ - main/include/ format. The only exception is // the DataAccessor.h header. Please note that moving files around in this structure // must be reflected by the header paths (this *will* change before full release to be // built and linked authomatically without needing the pathing). // update: updated to use long for some integers associated with file size to support large images. // Cunren Liang, 26-MAR-2018 #include #include #include #include #include #include #include #include #include "DataAccessor.h" #include "Constants.h" #include "Ellipsoid.h" #include "LinAlg.h" #include "Peg.h" #include "PegTrans.h" #include "TopoMethods.h" #include "Topo.h" #include "gpuTopo.h" using std::abs; using std::vector; #ifdef GPU_ACC_ENABLED #define RUN_GPU_TOPO 1 #else #define RUN_GPU_TOPO 0 #endif pthread_mutex_t m; struct writeData { void **accessors; //double **imgArrs; double *lat; double *lon; double *z; double *inc; double *los; bool incFlag; bool losFlag; int nLines; int width; bool firstWrite; }; void *writeToFile(void *inputData) { pthread_mutex_lock(&m); struct writeData data; data.accessors = ((struct writeData *)inputData)->accessors; //data.imgArrs = ((struct writeData *)inputData)->imgArrs; data.lat = ((struct writeData *)inputData)->lat; data.lon = ((struct writeData *)inputData)->lon; data.z = ((struct writeData *)inputData)->z; data.inc = ((struct writeData *)inputData)->inc; data.los = ((struct writeData *)inputData)->los; data.incFlag = ((struct writeData *)inputData)->incFlag; data.losFlag = ((struct writeData *)inputData)->losFlag; data.nLines = ((struct writeData *)inputData)->nLines; data.width = ((struct writeData *)inputData)->width; data.firstWrite = ((struct writeData *)inputData)->firstWrite; if (!data.firstWrite) { for (int i=0; isetLineSequential((char *)&data.lat[offset]); ((DataAccessor *)data.accessors[1])->setLineSequential((char *)&data.lon[offset]); ((DataAccessor *)data.accessors[2])->setLineSequential((char *)&data.z[offset]); if (data.incFlag) ((DataAccessor *)data.accessors[3])->setLineSequential((char *)&data.inc[2*offset]); if (data.losFlag) ((DataAccessor *)data.accessors[4])->setLineSequential((char *)&data.los[2*offset]); } free(data.lat); free(data.lon); free(data.z); free(data.inc); free(data.los); } pthread_mutex_unlock(&m); pthread_exit(NULL); } void Topo::createOrbit() { // Assumes that the state vars orbit_nvecs/orbit_basis have been set orb.setOrbit(orbit_nvecs,orbit_basis); } /* void Topo::writeToFile(void **accessors, double **imgArrs, bool incFlag, bool losFlag, int nLines, int width, bool firstWrite) { if (!firstWrite) { for (int i=0; isetLineSequential((char *)&imgArrs[0][offset]); ((DataAccessor *)accessors[1])->setLineSequential((char *)&imgArrs[1][offset]); ((DataAccessor *)accessors[2])->setLineSequential((char *)&imgArrs[2][offset]); if (incFlag) ((DataAccessor *)accessors[3])->setLineSequential((char *)&imgArrs[3][2*offset]); if (losFlag) ((DataAccessor *)accessors[4])->setLineSequential((char *)&imgArrs[4][2*offset]); } printf(" Finished writing %d lines.\n Freeing memory...\n", nLines); free(imgArrs[0]); free(imgArrs[1]); free(imgArrs[2]); free(imgArrs[3]); free(imgArrs[4]); printf(" Done.\n"); } } */ void Topo::topo() { vector > enumat(3,vector(3)), xyz2enu(3,vector(3)); vector sch(3), xyz(3), llh(3), delta(3), llh_prev(3), xyz_prev(3); vector xyzsat(3), velsat(3), llhsat(3), enu(3), that(3), chat(3); vector nhat(3), vhat(3), hgts(2); double ctrackmin,ctrackmax,dctrack,tline,rng,dopfact; double height,rcurv,vmag,aa,bb; //,hnadir; double beta,alpha,gamm,costheta,sintheta,cosalpha; double fraclat,fraclon,enunorm; // Vars for cropped DEM double umin_lon,umax_lon,umin_lat,umax_lat,ufirstlat,ufirstlon; double min_lat, min_lon, max_lat, max_lon; float demlat,demlon,demmax; int stat,totalconv,owidth,pixel,i_type,idemlat,idemlon; //,nearrangeflag; // Vars for cropped DEM int udemwidth,udemlength,ustartx,uendx,ustarty,uendy; // Data accessor objects DataAccessor *demAccObj = (DataAccessor*)demAccessor; DataAccessor *dopAccObj = (DataAccessor*)dopAccessor; DataAccessor *slrngAccObj = (DataAccessor*)slrngAccessor; DataAccessor *latAccObj = (DataAccessor*)latAccessor; DataAccessor *lonAccObj = (DataAccessor*)lonAccessor; DataAccessor *heightAccObj = (DataAccessor*)heightAccessor; DataAccessor *losAccObj = (DataAccessor*)losAccessor; DataAccessor *incAccObj = (DataAccessor*)incAccessor; DataAccessor *maskAccObj = (DataAccessor*)maskAccessor; // Local geometry-type objects Ellipsoid elp; Peg peg; PegTrans ptm; TopoMethods tzMethods; LinAlg linalg; // Set up DEM interpolation method if ((dem_method != SINC_METHOD) && (dem_method != BILINEAR_METHOD) && (dem_method != BICUBIC_METHOD) && (dem_method != NEAREST_METHOD) && (dem_method != AKIMA_METHOD) && (dem_method != BIQUINTIC_METHOD)) { printf("Error in Topo::topo - Undefined interpolation method.\n"); exit(1); } tzMethods.prepareMethods(dem_method); // Set up Ellipsoid object elp.a = major; elp.e2 = eccentricitySquared; // Set up orbit interpolation method if (orbit_method == HERMITE_METHOD) { if (orb.nVectors < 4) { printf("Error in Topo::topo - Need at least 4 state vectors for using hermite polynomial interpolation.\n"); exit(1); } } else if (orbit_method == SCH_METHOD) { if (orb.nVectors < 4) { printf("Error in Topo::topo - Need at least 4 state vectors for using SCH interpolation.\n"); exit(1); } } else if (orbit_method == LEGENDRE_METHOD) { if (orb.nVectors < 9) { printf("Error in Topo::topo - Need at least 9 state vectors for using legendre polynomial interpolation.\n"); exit(1); } } else { printf("Error in Topo::topo - Undefined orbit interpolation method.\n"); exit(1); } owidth = (2 * width) + 1; totalconv = 0; height = 0.0; min_lat = 10000.0; max_lat = -10000.0; min_lon = 10000.0; max_lon = -10000.0; printf("Max threads used: %d\n", omp_get_max_threads()); if ((slrngAccessor == 0) && (r0 == 0.0)) { printf("Error in Topo::topo - Both the slant range accessor and starting range are zero.\n"); exit(1); } vector lat(width), lon(width), z(width), zsch(width), rho(width), dopline(width), converge(width); vector distance(width), losang(2*width), incang(2*width); vector omask(0), orng(0), ctrack(0), oview(0), mask(0); // Initialize (so no scoping errors), resize only if needed if (maskAccessor > 0) { omask.resize(owidth); orng.resize(owidth); ctrack.resize(owidth); oview.resize(owidth); mask.resize(width); } //nearrangeflag = 0; hgts[0] = MIN_H; hgts[1] = MAX_H; // Few extra steps to let std::vector interface with getLine double *raw_line = new double[width]; dopAccObj->getLine((char *)raw_line,0); dopline.assign(raw_line,(raw_line+width)); slrngAccObj->getLine((char *)raw_line,0); rho.assign(raw_line,(raw_line+width)); delete[] raw_line; // Manage data VERY carefully! // First line for (int line=0; line<2; line++) { tline = t0 + (line * Nazlooks * ((length - 1.0) / prf)); stat = orb.interpolateOrbit(tline,xyzsat,velsat,orbit_method); if (stat != 0) { printf("Error in Topo::topo - Error getting state vector for bounds computation.\n"); exit(1); } vmag = linalg.norm(velsat); linalg.unitvec(velsat,vhat); elp.latlon(xyzsat,llhsat,XYZ_2_LLH); height = llhsat[2]; elp.tcnbasis(xyzsat,velsat,that,chat,nhat); peg.lat = llhsat[0]; peg.lon = llhsat[1]; peg.hdg = peghdg; ptm.radar_to_xyz(elp,peg); rcurv = ptm.radcur; for (int ind=0; ind<2; ind++) { pixel = ind * (width - 1); rng = rho[pixel]; dopfact = (0.5 * wvl * (dopline[pixel] / vmag)) * rng; for (int iter=0; iter<2; iter++) { // SWOT-specific near range check // If slant range vector doesn't hit ground, pick nadir point if (rng <= (llhsat[2] - hgts[iter] + 1.0)) { for (int idx=0; idx<3; idx++) llh[idx] = llhsat[idx]; //printf("Possible near nadir imaging.\n"); //nearrangeflag = 1; } else { zsch[pixel] = hgts[iter]; aa = height + rcurv; bb = rcurv + zsch[pixel]; costheta = 0.5 * ((aa / rng) + (rng / aa) - ((bb / aa) * (bb / rng))); sintheta = sqrt(1.0 - (costheta * costheta)); gamm = costheta * rng; alpha = (dopfact - (gamm * linalg.dot(nhat,vhat))) / linalg.dot(vhat,that); beta = -ilrl * sqrt((rng * rng * sintheta * sintheta) - (alpha * alpha)); for (int idx=0; idx<3; idx++) delta[idx] = (gamm * nhat[idx]) + (alpha * that[idx]) + (beta * chat[idx]); for (int idx=0; idx<3; idx++) xyz[idx] = xyzsat[idx] + delta[idx]; elp.latlon(xyz,llh,XYZ_2_LLH); } min_lat = min(min_lat, (llh[0]*(180./M_PI))); max_lat = max(max_lat, (llh[0]*(180./M_PI))); min_lon = min(min_lon, (llh[1]*(180./M_PI))); max_lon = max(max_lon, (llh[1]*(180./M_PI))); } } } // Account for margins min_lon = min_lon - MARGIN; max_lon = max_lon + MARGIN; min_lat = min_lat - MARGIN; max_lat = max_lat + MARGIN; printf("DEM parameters:\n"); printf("Dimensions: %d %d\n", idemwidth, idemlength); printf("Top Left: %g %g\n", firstlon, firstlat); printf("Spacing: %g %g\n", deltalon, deltalat); printf("Lon: %g %g\n", firstlon, (firstlon+(idemwidth-1)*deltalon)); printf("Lat: %g %g\n\n", (firstlat+((idemlength-1)*deltalat)), firstlat); printf("Estimated DEM bounds needed for global height range:\n"); printf("Lon: %g %g\n", min_lon, max_lon); printf("Lat: %g %g\n", min_lat, max_lat); // Compare with what has been provided as input umin_lon = max(min_lon, firstlon); umax_lon = min(max_lon, (firstlon+((idemwidth-1)*deltalon))); umax_lat = min(max_lat, firstlat); umin_lat = max(min_lat, (firstlat+((idemlength-1)*deltalat))); if (min_lon < firstlon) printf("Warning: West limit may be insufficient for global height range.\n"); if (max_lon > (firstlon+((idemwidth-1)*deltalon))) printf("Warning: East limit may be insufficient for global height range.\n"); if (max_lat > firstlat) printf("Warning: North limit may be insufficient for global height range.\n"); if (min_lat < (firstlat+((idemlength-1)*deltalat))) printf("Warning: South limit may be insufficient for global height range.\n"); // Usable part of the DEM limits ustartx = int((umin_lon - firstlon) / deltalon); uendx = int(((umax_lon - firstlon) / deltalon) + 0.5); ustarty = int((umax_lat - firstlat) / deltalat); uendy = int(((umin_lat - firstlat) / deltalat) + 0.5); if (ustartx < 1) ustartx = 1; if (uendx > idemwidth) uendx = idemwidth; if (ustarty < 1) ustarty = 1; if (uendy > idemlength) ustarty = idemlength; ufirstlon = firstlon + (deltalon * (ustartx)); ufirstlat = firstlat + (deltalat * (ustarty)); udemwidth = uendx - ustartx + 1; udemlength = uendy - ustarty + 1; printf("\nActual DEM bounds used:\n"); printf("Dimensions: %d %d\n", udemwidth, udemlength); printf("Top Left: %g %g\n", ufirstlon, ufirstlat); printf("Spacing: %g %g\n", deltalon, deltalat); printf("Lon: %g %g\n", ufirstlon, (ufirstlon+(deltalon*(udemwidth-1)))); printf("Lat: %g %g\n", (ufirstlat+(deltalat*(udemlength-1))), ufirstlat); printf("Lines: %d %d\n", ustarty, uendy); printf("Pixels: %d %d\n", ustartx, uendx); vector > dem(udemwidth,vector(udemlength)); vector demline(idemwidth); float *raw_line_f = new float[idemwidth]; // Safest way to copy in the DEM using the same std::vector-getLine interface // Read the useful part of the DEM for (int j=0; jgetLine((char *)raw_line_f,(j + ustarty)); demline.assign(raw_line_f,(raw_line_f + idemwidth)); for (int ii=0; ii demmax) demmax = dem[i][j]; } } printf("Max DEM height: %g\n", demmax); printf("Primary iterations: %d\n", numiter); printf("Secondary iterations: %d\n", extraiter); printf("Distance threshold: %g\n", thresh); height = 0.0; min_lat = 10000.0; max_lat = -10000.0; min_lon = 10000.0; max_lon = -10000.0; raw_line = new double[width]; if (RUN_GPU_TOPO) { double gpu_inputs_d[14]; int gpu_inputs_i[7]; gpu_inputs_d[0] = t0; gpu_inputs_d[1] = prf; gpu_inputs_d[2] = elp.a; gpu_inputs_d[3] = elp.e2; gpu_inputs_d[4] = peg.lat; gpu_inputs_d[5] = peg.lon; gpu_inputs_d[6] = peg.hdg; gpu_inputs_d[7] = ufirstlat; gpu_inputs_d[8] = ufirstlon; gpu_inputs_d[9] = deltalat; gpu_inputs_d[10] = deltalon; gpu_inputs_d[11] = wvl; gpu_inputs_d[12] = ilrl; gpu_inputs_d[13] = thresh; gpu_inputs_i[0] = Nazlooks; gpu_inputs_i[1] = width; gpu_inputs_i[2] = udemlength; gpu_inputs_i[3] = udemwidth; gpu_inputs_i[4] = numiter; gpu_inputs_i[5] = extraiter; gpu_inputs_i[6] = length; printf("\n\nCopying Orbit and DEM data to compatible arrays...\n"); float *gpu_dem = new float[size_t(udemlength)*udemwidth]; for (int i=0; i 0); bool losFlag = bool(losAccessor > 0); //std::future result = std::async(std::launch::async, &Topo::writeToFile, this, (void **)accObjs, outputArrays, incFlag, losFlag, 0, width, true); // Create pthread data and initialize dummy thread pthread_t writeThread; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); void *thread_stat; struct writeData wd; wd.accessors = (void**)accObjs; //wd.imgArrs = outputArrays; wd.lat = outputArrays[0]; wd.lon = outputArrays[1]; wd.z = outputArrays[2]; wd.inc = outputArrays[3]; wd.los = outputArrays[4]; wd.incFlag = incFlag; wd.losFlag = losFlag; wd.nLines = 0; wd.width = width; wd.firstWrite = true; pthread_create(&writeThread, &attr, writeToFile, (void*)&wd); // Calculate number of and size of blocks size_t num_GPU_bytes = getDeviceMem(); long totalPixels = (long)length * width; long pixPerImg = (((num_GPU_bytes / 8) / 9) / 1e7) * 1e7; // Round down to the nearest 10M pixels long linesPerImg = pixPerImg / width; pixPerImg = linesPerImg * width; int nBlocks = totalPixels / pixPerImg; //original values: 1.5e8 is too large for each of GPU on kamb. //here I change it to 1.0e8. 16-MAY-2018, Cunren Liang while (pixPerImg > 1.0e8) { linesPerImg -= 1; pixPerImg -= width; nBlocks = totalPixels / pixPerImg; } long remPix = totalPixels - (pixPerImg * nBlocks); long remLines = remPix / width; printf("NOTE: GPU will process image in %d blocks of %d lines", nBlocks, linesPerImg); if (remPix > 0) printf(" (with %d lines in a final partial block)", remLines); printf("\n"); double *gpu_rho = new double[linesPerImg * width]; double *gpu_dopline = new double[linesPerImg * width]; size_t nb_pixels = pixPerImg * sizeof(double); printf("\n\n ------------------ INITIALIZING GPU TOPO ------------------\n\n"); // Call GPU kernel on blocks for (int i=0; igetLineSequential((char *)raw_line); for (int k=0; kgetLineSequential((char *)raw_line); for (int k=0; k 0) { nb_pixels = remPix * sizeof(double); outputArrays[0] = (double *)malloc(nb_pixels); outputArrays[1] = (double *)malloc(nb_pixels); outputArrays[2] = (double *)malloc(nb_pixels); outputArrays[3] = (double *)malloc(2 * nb_pixels); outputArrays[4] = (double *)malloc(2 * nb_pixels); printf(" Loading slantrange and doppler data...\n"); for (int i=0; igetLineSequential((char *)raw_line); for (int j=0; jgetLineSequential((char *)raw_line); for (int j=0; jgetLineSequential((char *)raw_line); dopline.assign(raw_line,(raw_line + width)); // Get the slant range slrngAccObj->getLineSequential((char *)raw_line); rho.assign(raw_line,(raw_line + width)); // Step 4: Set up SCH basis right below the satellite peg.lat = llhsat[0]; peg.lon = llhsat[1]; peg.hdg = peghdg; //hnadir = 0.0; ptm.radar_to_xyz(elp,peg); rcurv = ptm.radcur; for (int idx=0; idx (udemlength - 1)) demlat = udemlength - 1; // if (demlon < 1) demlon = 1; // if (demlon > (udemwidth - 1)) demlon = udemwidth - 1; // idemlat = int(demlat); // idemlon = int(demlon); // fraclat = demlat - idemlat; // fraclon = demlon - idemlon; // hnadir = tzMethods.interpolate(dem,idemlon,idemlat,fraclon,fraclat,udemwidth,udemlength,dem_method); //} // Start the iterations for (int iter=0; iter<=(numiter+extraiter); iter++) { #pragma omp parallel for private(pixel,beta,alpha,gamm,idemlat,idemlon,fraclat,fraclon,\ demlat,demlon,aa,bb,rng,costheta,sintheta,dopfact) \ firstprivate(sch,llh,xyz,llh_prev,xyz_prev,delta) \ reduction(+:totalconv) // Optimized atomic accumulation of totalconv for (pixel=0; pixel (udemlength-1)) demlat = udemlength - 1; if (demlon < 1) demlon = 1; if (demlon > (udemwidth-1)) demlon = udemwidth - 1; idemlat = int(demlat); idemlon = int(demlon); fraclat = demlat - idemlat; fraclon = demlon - idemlon; z[pixel] = tzMethods.interpolate(dem,idemlon,idemlat,fraclon,fraclat,udemwidth,udemlength,dem_method); if (z[pixel] < -500.0) z[pixel] = -500.0; // Given llh, where h = z(pixel, line) in WGS84, get the SCH height llh[0] = lat[pixel] / (180. / M_PI); llh[1] = lon[pixel] / (180. / M_PI); llh[2] = z[pixel]; elp.latlon(xyz,llh,LLH_2_XYZ); ptm.convert_sch_to_xyz(sch,xyz,XYZ_2_SCH); zsch[pixel] = sch[2]; // Absolute distance distance[pixel] = sqrt(pow((xyz[0]-xyzsat[0]),2)+pow((xyz[1]-xyzsat[1]),2) + pow((xyz[2]-xyzsat[2]),2)) - rng; if (abs(distance[pixel]) <= thresh) { zsch[pixel] = sch[2]; converge[pixel] = 1; totalconv = totalconv + 1; } else if (iter > numiter) { elp.latlon(xyz_prev,llh_prev,LLH_2_XYZ); for (int idx=0; idx<3; idx++) xyz[idx] = 0.5 * (xyz_prev[idx] + xyz[idx]); // Repopulate lat, lon, z elp.latlon(xyz,llh,XYZ_2_LLH); lat[pixel] = llh[0] * (180. / M_PI); lon[pixel] = llh[1] * (180. / M_PI); z[pixel] = llh[2]; ptm.convert_sch_to_xyz(sch,xyz,XYZ_2_SCH); zsch[pixel] = sch[2]; // Absolute distance distance[pixel] = sqrt(pow((xyz[0]-xyzsat[0]),2)+pow((xyz[1]-xyzsat[1]),2) + pow((xyz[2]-xyzsat[2]),2)) - rng; } } } //end OMP for loop } // Final computation. // The output points are exactly at range pixel // Distance from the satellite #pragma omp parallel for private(pixel,cosalpha,rng,aa,bb,alpha,beta,gamm,costheta,sintheta,dopfact,\ demlat,demlon,idemlat,idemlon,fraclat,fraclon,enunorm) \ firstprivate(xyz,llh,delta,enumat,xyz2enu,enu) for (pixel=0; pixel (udemlength-1)) demlat = udemlength - 1; if (demlon < 2) demlon = 2; if (demlon > (udemwidth-1)) demlon = udemwidth - 1; idemlat = int(demlat); idemlon = int(demlon); fraclat = demlat - idemlat; fraclon = demlon - idemlon; gamm = lat[pixel] / (180. / M_PI); // Slopex aa = tzMethods.interpolate(dem,(idemlon-1),idemlat,fraclon,fraclat,udemwidth,udemlength,dem_method); bb = tzMethods.interpolate(dem,(idemlon+1),idemlat,fraclon,fraclat,udemwidth,udemlength,dem_method); alpha = ((bb - aa) * (180. / M_PI)) / (2.0 * elp.reast(gamm) * deltalon); // Slopey aa = tzMethods.interpolate(dem,idemlon,(idemlat-1),fraclon,fraclat,udemwidth,udemlength,dem_method); bb = tzMethods.interpolate(dem,idemlon,(idemlat+1),fraclon,fraclat,udemwidth,udemlength,dem_method); beta = ((bb - aa) * (180. / M_PI)) / (2.0 * elp.rnorth(gamm) * deltalat); enunorm = linalg.norm(enu); for (int idx=0; idx<3; idx++) enu[idx] = enu[idx] / enunorm; costheta = ((enu[0] * alpha) + (enu[1] * beta) - enu[2]) / sqrt(1.0 + (alpha * alpha) + (beta * beta)); incang[((2*pixel)+1)] = acos(costheta) * (180. / M_PI); } //end OMP for loop double mnlat,mxlat,mnlon,mxlon; mnlat = mnlon = 10000.0; mxlat = mxlon = -10000.0; for (int ii=0; ii mxlat) mxlat = lat[ii]; if (lon[ii] < mnlon) mnlon = lon[ii]; if (lon[ii] > mxlon) mxlon = lon[ii]; } min_lat = min(mnlat, min_lat); max_lat = max(mxlat, max_lat); min_lon = min(mnlon, min_lon); max_lon = max(mxlon, max_lon); latAccObj->setLineSequential((char *)&lat[0]); lonAccObj->setLineSequential((char *)&lon[0]); heightAccObj->setLineSequential((char *)&z[0]); if (losAccessor > 0) losAccObj->setLineSequential((char *)&losang[0]); if (incAccessor > 0) incAccObj->setLineSequential((char *)&incang[0]); if (maskAccessor > 0) { double mnzsch,mxzsch; mnzsch = 10000.0; mxzsch = -10000.0; for (int ii=0; ii mxzsch) mxzsch = zsch[ii]; } ctrackmin = mnzsch - demmax; ctrackmax = mxzsch + demmax; dctrack = (ctrackmax - ctrackmin) / (owidth - 1.0); // Sort lat/lon by ctrack linalg.insertionSort(zsch,width); linalg.insertionSort(lat,width); linalg.insertionSort(lon,width); #pragma omp parallel for private(pixel,aa,bb,i_type,demlat,demlon,\ idemlat,idemlon,fraclat,fraclon) \ firstprivate(llh,xyz) for (pixel=0; pixel (udemlength-1)) demlat = udemlength - 1; if (demlon < 2) demlon = 2; if (demlon > (udemwidth-1)) demlon = udemwidth - 1; idemlat = int(demlat); idemlon = int(demlon); fraclat = demlat - idemlat; fraclon = demlon - idemlon; llh[2] = tzMethods.interpolate(dem,idemlon,idemlat,fraclon,fraclat,udemwidth,udemlength,dem_method); elp.latlon(xyz,llh,LLH_2_XYZ); for (int idx=0; idx<3; idx++) xyz[idx] = xyz[idx] - xyzsat[idx]; bb = linalg.norm(xyz); orng[pixel] = bb; aa = abs((nhat[0] * xyz[0]) + (nhat[1] * xyz[1]) + (nhat[2] * xyz[2])); oview[pixel] = acos(aa / bb) * (180. / M_PI); } //end OMP for loop // Again sort in terms of slant range linalg.insertionSort(orng,owidth); linalg.insertionSort(ctrack,owidth); linalg.insertionSort(oview,owidth); for (int idx=0; idx=0; pixel--) { bb = incang[(2*pixel)]; if (bb >= aa) mask[pixel] = 1; else aa = bb; } aa = ctrack[0]; for (pixel=1; pixel=0; pixel--) { bb = ctrack[pixel]; if ((bb >= aa) && (omask[pixel] < 2)) omask[pixel] = omask[pixel] + 2; else aa = bb; } for (pixel=0; pixel 0) { idemlat = linalg.binarySearch(rho,0,(width-1),orng[pixel]); if (mask[idemlat] < omask[pixel]) mask[idemlat] = mask[idemlat] + omask[pixel]; } } maskAccObj->setLineSequential((char *)&mask[0]); } } delete[] raw_line; printf("Total convergence: %d out of %d.\n", totalconv, (width * length)); } }