From b2008590e7c4ff505f4410b5086acf61a08d4e2f Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 11:54:23 +0000 Subject: [PATCH 01/12] Correctly detect missing clutter file --- inputs.cc | 184 +++++++++++++++++++++++++++--------------------------- main.cc | 7 ++- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/inputs.cc b/inputs.cc index c3561af..029cd0b 100644 --- a/inputs.cc +++ b/inputs.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "common.h" #include "main.hh" @@ -22,105 +23,104 @@ int loadClutter(char *filename, double radius, struct site tx) char * pch; FILE *fd; - fd = fopen(filename, "rb"); + if( (fd = fopen(filename, "rb")) == NULL) + return errno; - if (fd != NULL) { + if (fgets(line, 19, fd) != NULL) { + pch = strtok (line," "); + pch = strtok (NULL, " "); + w = atoi(pch); + } - if (fgets(line, 19, fd) != NULL) { - pch = strtok (line," "); - pch = strtok (NULL, " "); - w = atoi(pch); - } - - if (fgets(line, 19, fd) != NULL) { - //pch = strtok (line," "); - //pch = strtok (NULL, " "); - h = atoi(pch); - } - - if(w==2880 && h==3840){ - cellsize=0.004167; - cellsize2 = cellsize * 2; - }else{ - return 0; // can't work with this yet - } - if (debug) { - fprintf(stderr, "\nLoading clutter file \"%s\" %d x %d...\n", filename, w,h); - fflush(stderr); - } - if (fgets(line, 25, fd) != NULL) { - sscanf(pch, "%lf", &xll); - } - - fgets(line, 25, fd); - if (fgets(line, 25, fd) != NULL) { - sscanf(pch, "%lf", &yll); - } + if (fgets(line, 19, fd) != NULL) { + //pch = strtok (line," "); + //pch = strtok (NULL, " "); + h = atoi(pch); + } + if(w==2880 && h==3840){ + cellsize=0.004167; + cellsize2 = cellsize * 2; + }else{ + return 0; // can't work with this yet + } if (debug) { - fprintf(stderr, "\nxll %.2f yll %.2f\n", xll, yll); + fprintf(stderr, "\nLoading clutter file \"%s\" %d x %d...\n", filename, w,h); fflush(stderr); } - - fgets(line, 25, fd); // cellsize - - //loop over matrix - for (y = h; y > 0; y--) { - x = 0; - if (fgets(line, 100000, fd) != NULL) { - pch = strtok(line, " "); - while (pch != NULL && x < w) { - z = atoi(pch); - - // Apply ITU-R P.452-11 - // Treat classes 0, 9, 10, 11, 15, 16 as water, (Water, savanna, grassland, wetland, snow, barren) - clh = 0.0; - - // evergreen, evergreen, urban - if(z == 1 || z == 2 || z == 13) - clh = 20.0; - // deciduous, deciduous, mixed - if(z==3 || z==4 || z==5) - clh = 15.0; - // woody shrublands & savannas - if(z==6 || z==8) - clh = 4.0; - // shurblands, savannas, croplands... - if(z==7 || z==9 || z==10 || z==12 || z==14) - clh = 2.0; - - if(clh>1){ - xOffset=x*cellsize; // 12 deg wide - yOffset=y*cellsize; // 16 deg high - - // make all longitudes positive - if(xll+xOffset>0){ - lon=360-(xll+xOffset); - }else{ - lon=(xll+xOffset)*-1; - } - lat = yll+yOffset; - - // bounding box - if(lat > tx.lat - radius && lat < tx.lat + radius && lon > tx.lon - radius && lon < tx.lon + radius){ - - // not in near field - if((lat > tx.lat+cellsize2 || lat < tx.lat-cellsize2) || (lon > tx.lon + cellsize2 || lon < tx.lon - cellsize2)){ - AddElevation(lat,lon,clh,3); - - } - - } - } - - x++; - pch = strtok(NULL, " "); - }//while - } else { - fprintf(stderr, "Clutter error @ x %d y %d\n", x, y); - }//if - }//for + if (fgets(line, 25, fd) != NULL) { + sscanf(pch, "%lf", &xll); } + + fgets(line, 25, fd); + if (fgets(line, 25, fd) != NULL) { + sscanf(pch, "%lf", &yll); + } + + if (debug) { + fprintf(stderr, "\nxll %.2f yll %.2f\n", xll, yll); + fflush(stderr); + } + + fgets(line, 25, fd); // cellsize + + //loop over matrix + for (y = h; y > 0; y--) { + x = 0; + if (fgets(line, 100000, fd) != NULL) { + pch = strtok(line, " "); + while (pch != NULL && x < w) { + z = atoi(pch); + + // Apply ITU-R P.452-11 + // Treat classes 0, 9, 10, 11, 15, 16 as water, (Water, savanna, grassland, wetland, snow, barren) + clh = 0.0; + + // evergreen, evergreen, urban + if(z == 1 || z == 2 || z == 13) + clh = 20.0; + // deciduous, deciduous, mixed + if(z==3 || z==4 || z==5) + clh = 15.0; + // woody shrublands & savannas + if(z==6 || z==8) + clh = 4.0; + // shurblands, savannas, croplands... + if(z==7 || z==9 || z==10 || z==12 || z==14) + clh = 2.0; + + if(clh>1){ + xOffset=x*cellsize; // 12 deg wide + yOffset=y*cellsize; // 16 deg high + + // make all longitudes positive + if(xll+xOffset>0){ + lon=360-(xll+xOffset); + }else{ + lon=(xll+xOffset)*-1; + } + lat = yll+yOffset; + + // bounding box + if(lat > tx.lat - radius && lat < tx.lat + radius && lon > tx.lon - radius && lon < tx.lon + radius){ + + // not in near field + if((lat > tx.lat+cellsize2 || lat < tx.lat-cellsize2) || (lon > tx.lon + cellsize2 || lon < tx.lon - cellsize2)){ + AddElevation(lat,lon,clh,3); + + } + + } + } + + x++; + pch = strtok(NULL, " "); + }//while + } else { + fprintf(stderr, "Clutter error @ x %d y %d\n", x, y); + }//if + }//for + fclose(fd); return 0; } diff --git a/main.cc b/main.cc index eae3b62..81f5e99 100644 --- a/main.cc +++ b/main.cc @@ -1042,7 +1042,7 @@ int main(int argc, char *argv[]) int x, y, z = 0, min_lat, min_lon, max_lat, max_lon, rxlat, rxlon, txlat, txlon, west_min, west_max, nortRxHin, nortRxHax, propmodel, knifeedge = 0, ppa = - 0, normalise = 0, haf = 0, pmenv = 1, lidar=0, cropped; + 0, normalise = 0, haf = 0, pmenv = 1, lidar=0, cropped, result; bool use_threads = true; @@ -1797,7 +1797,10 @@ int main(int argc, char *argv[]) Clutter tiles cover 16 x 12 degs but we only need a fraction of that area. Limit by max_range / miles per degree (at equator) */ - loadClutter(clutter_file,max_range/45,tx_site[0]); + if( (result = loadClutter(clutter_file,max_range/45,tx_site[0])) != 0 ){ + fprintf(stderr, "Error, invalid or clutter file not found\n"); + return result; + } } if (ppa == 0) { From 3de2bf8f971821d1857c0aec751f4cacdf4be99e Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 12:08:21 +0000 Subject: [PATCH 02/12] Elegantly handle missing LIDAR tiles --- inputs.cc | 184 ++++++++++++++++++++++++++---------------------------- main.cc | 8 +-- 2 files changed, 92 insertions(+), 100 deletions(-) diff --git a/inputs.cc b/inputs.cc index 029cd0b..ddca569 100644 --- a/inputs.cc +++ b/inputs.cc @@ -234,107 +234,103 @@ int loadLIDAR(char *filenames) } while (indx < fc) { - fd = fopen(files[indx], "rb"); + if( (fd = fopen(files[indx], "rb")) == NULL ) + return errno; - if (fd != NULL) { + if (fgets(line, 255, fd) != NULL) { + pch = strtok (line," "); + pch = strtok (NULL, " "); + width = atoi(pch); // ncols - if (fgets(line, 255, fd) != NULL) { - pch = strtok (line," "); - pch = strtok (NULL, " "); - width = atoi(pch); // ncols + if (debug) { + fprintf(stderr, "Loading \"%s\" into page %d with width %d...\n", files[indx], indx, width); + fflush(stderr); + } - if (debug) { - fprintf(stderr, "Loading \"%s\" into page %d with width %d...\n", files[indx], indx, width); - fflush(stderr); + if (fgets(line, 255, fd) != NULL) + height = atoi(pch); // nrows + + if (!dem_alloced) { + //Reduce MAXPAGES to increase speed + MAXPAGES=fc; + if(width>height){ + IPPD = width; + }else{ + IPPD = height; } - - if (fgets(line, 255, fd) != NULL) - height = atoi(pch); // nrows - - if (!dem_alloced) { - //Reduce MAXPAGES to increase speed - MAXPAGES=fc; - if(width>height){ - IPPD = width; - }else{ - IPPD = height; - } - // add fudge as reprojected tiles sometimes vary by a pixel or ten - IPPD+=50; - ARRAYSIZE = (MAXPAGES * IPPD)+50; - do_allocs(); - dem_alloced = 1; - } - - } - if (fgets(line, 255, fd) != NULL) { - sscanf(pch, "%lf", &xll); // xll + // add fudge as reprojected tiles sometimes vary by a pixel or ten + IPPD+=50; + ARRAYSIZE = (MAXPAGES * IPPD)+50; + do_allocs(); + dem_alloced = 1; } - if (fgets(line, 255, fd) != NULL) { - sscanf(pch, "%lf", &yll); // yll - } - - if (fgets(line, 255, fd) != NULL) - sscanf(pch, "%lf", &cellsize); - - avgCellsize=avgCellsize+cellsize; - - /*if(cellsize>=0.5){ // 50cm LIDAR? - // compute xur and yur with inverse haversine if cellsize in *metres* - double roundDistance = (width*cellsize)/6371000; - yur = asin(sin(yll*DEG2RAD) * cos(roundDistance) + cos(yll * DEG2RAD) * sin(roundDistance) * cos(0)) * TO_DEG; - xur = ((xll*DEG2RAD) + atan2(sin(90*DEG2RAD) * sin(roundDistance) * cos(yll*DEG2RAD), cos(roundDistance) - sin(yll * DEG2RAD) * sin(yur*DEG2RAD))) * TO_DEG; - }else{*/ - // Degrees with GDAL option: -co "FORCE_CELLSIZE=YES" - xur = xll+(cellsize*width); - yur = yll+(cellsize*height); - //} - - if (xur > eastoffset) - eastoffset = xur; - if (xll < westoffset) - westoffset = xll; - - if (debug) - fprintf(stderr,"%d, %d, %.7f, %.7f, %.7f, %.7f, %.7f\n",width,height,xll,yll,cellsize,yur,xur); - - - // Greenwich straddling hack - if (xll <= 0 && xur > 0) { - xll = (xur - xll); // full width - xur = 0.0; // budge it along so it's west of greenwich - delta = eastoffset; // add to Tx longitude later - } else { - // Transform WGS84 longitudes into 'west' values as society finishes east of Greenwich ;) - if (xll >= 0) - xll = 360-xll; - if(xur >= 0) - xur = 360-xur; - if(xll < 0) - xll = xll * -1; - if(xur < 0) - xur = xur * -1; - } - if (debug) - fprintf(stderr, "POST yll %.7f yur %.7f xur %.7f xll %.7f delta %.6f\n", yll, yur, xur, xll, delta); - - - fgets(line, 255, fd); // NODATA - pos = ftell(fd); - - // tile 0 [x| ] - if (debug) - fprintf(stderr, "readLIDAR(fd,%d,%d,%d,%.4f,%.4f,%.4f,%.4f)\n", height, width, indx, yur, xur, yll, xll); - - readLIDAR(fd, height, width, indx, yur, xur, yll, xll); - - fclose(fd); - if (debug) - fprintf(stderr, "LIDAR LOADED %d x %d\n", width, height); - } else { - return -1; } + if (fgets(line, 255, fd) != NULL) { + sscanf(pch, "%lf", &xll); // xll + } + + if (fgets(line, 255, fd) != NULL) { + sscanf(pch, "%lf", &yll); // yll + } + + if (fgets(line, 255, fd) != NULL) + sscanf(pch, "%lf", &cellsize); + + avgCellsize=avgCellsize+cellsize; + + /*if(cellsize>=0.5){ // 50cm LIDAR? + // compute xur and yur with inverse haversine if cellsize in *metres* + double roundDistance = (width*cellsize)/6371000; + yur = asin(sin(yll*DEG2RAD) * cos(roundDistance) + cos(yll * DEG2RAD) * sin(roundDistance) * cos(0)) * TO_DEG; + xur = ((xll*DEG2RAD) + atan2(sin(90*DEG2RAD) * sin(roundDistance) * cos(yll*DEG2RAD), cos(roundDistance) - sin(yll * DEG2RAD) * sin(yur*DEG2RAD))) * TO_DEG; + }else{*/ + // Degrees with GDAL option: -co "FORCE_CELLSIZE=YES" + xur = xll+(cellsize*width); + yur = yll+(cellsize*height); + //} + + if (xur > eastoffset) + eastoffset = xur; + if (xll < westoffset) + westoffset = xll; + + if (debug) + fprintf(stderr,"%d, %d, %.7f, %.7f, %.7f, %.7f, %.7f\n",width,height,xll,yll,cellsize,yur,xur); + + + // Greenwich straddling hack + if (xll <= 0 && xur > 0) { + xll = (xur - xll); // full width + xur = 0.0; // budge it along so it's west of greenwich + delta = eastoffset; // add to Tx longitude later + } else { + // Transform WGS84 longitudes into 'west' values as society finishes east of Greenwich ;) + if (xll >= 0) + xll = 360-xll; + if(xur >= 0) + xur = 360-xur; + if(xll < 0) + xll = xll * -1; + if(xur < 0) + xur = xur * -1; + } + if (debug) + fprintf(stderr, "POST yll %.7f yur %.7f xur %.7f xll %.7f delta %.6f\n", yll, yur, xur, xll, delta); + + + fgets(line, 255, fd); // NODATA + pos = ftell(fd); + + // tile 0 [x| ] + if (debug) + fprintf(stderr, "readLIDAR(fd,%d,%d,%d,%.4f,%.4f,%.4f,%.4f)\n", height, width, indx, yur, xur, yll, xll); + + readLIDAR(fd, height, width, indx, yur, xur, yll, xll); + + fclose(fd); + if (debug) + fprintf(stderr, "LIDAR LOADED %d x %d\n", width, height); indx++; } // filename(s) IPPD=width; diff --git a/main.cc b/main.cc index 81f5e99..33f3173 100644 --- a/main.cc +++ b/main.cc @@ -1665,17 +1665,13 @@ int main(int argc, char *argv[]) /* Load the required tiles */ if(lidar){ - int err; - - err = loadLIDAR(lidar_tiles); - if (err) { + if( (result = loadLIDAR(lidar_tiles)) != 0 ){ fprintf(stderr, "Couldn't find one or more of the " "lidar files. Please ensure their paths are " "correct and try again.\n"); - exit(EXIT_FAILURE); + exit(result); } - if(debug){ fprintf(stderr,"%.4f,%.4f,%.4f,%.4f,%d x %d\n",max_north,min_west,min_north,max_west,width,height); } From 1a4f4bd2269cabfcb277c958b7cd2448cc3dea69 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 13:39:14 +0000 Subject: [PATCH 03/12] Elegantly handle missing sdf files --- inputs.cc | 243 ++++++++++++++++++++++++++---------------------------- 1 file changed, 119 insertions(+), 124 deletions(-) diff --git a/inputs.cc b/inputs.cc index ddca569..a87703f 100644 --- a/inputs.cc +++ b/inputs.cc @@ -400,138 +400,133 @@ int LoadSDF_SDF(char *name) strncpy(path_plus_name, sdf_file, 255); - fd = fopen(path_plus_name, "rb"); - - if (fd == NULL) { + if( (fd = fopen(path_plus_name, "rb")) == NULL ){ /* Next, try loading SDF file from path specified in $HOME/.ss_path file or by -d argument */ strncpy(path_plus_name, sdf_path, 255); strncat(path_plus_name, sdf_file, 255); - fd = fopen(path_plus_name, "rb"); + if( (fd = fopen(path_plus_name, "rb")) == NULL ){ + return -errno; + } } - if (fd != NULL) { - if (debug == 1) { - fprintf(stderr, - "Loading \"%s\" into page %d...", - path_plus_name, indx + 1); - fflush(stderr); - } - - if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].max_west); - } - - if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].min_north); - } - - if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].min_west); - } - - if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].max_north); - } - /* - Here X lines of DEM will be read until IPPD is reached. - Each .sdf tile contains 1200x1200 = 1.44M 'points' - Each point is sampled for 1200 resolution! - */ - for (x = 0; x < ippd; x++) { - for (y = 0; y < ippd; y++) { - - for (j = 0; j < jgets; j++) { - junk = fgets(jline, 19, fd); - } - - if (fgets(line, 19, fd) != NULL) { - data = atoi(line); - } - - dem[indx].data[x][y] = data; - dem[indx].signal[x][y] = 0; - dem[indx].mask[x][y] = 0; - - if (data > dem[indx].max_el) - dem[indx].max_el = data; - - if (data < dem[indx].min_el) - dem[indx].min_el = data; - - } - - if (ippd == 600) { - for (j = 0; j < IPPD; j++) { - junk = fgets(jline, 19, fd); - } - } - if (ippd == 300) { - for (j = 0; j < IPPD; j++) { - junk = fgets(jline, 19, fd); - junk = fgets(jline, 19, fd); - junk = fgets(jline, 19, fd); - - } - } - } - - fclose(fd); - - if (dem[indx].min_el < min_elevation) - min_elevation = dem[indx].min_el; - - if (dem[indx].max_el > max_elevation) - max_elevation = dem[indx].max_el; - - if (max_north == -90) - max_north = dem[indx].max_north; - - else if (dem[indx].max_north > max_north) - max_north = dem[indx].max_north; - - if (min_north == 90) - min_north = dem[indx].min_north; - - else if (dem[indx].min_north < min_north) - min_north = dem[indx].min_north; - - if (max_west == -1) - max_west = dem[indx].max_west; - - else { - if (abs(dem[indx].max_west - max_west) < 180) { - if (dem[indx].max_west > max_west) - max_west = dem[indx].max_west; - } - - else { - if (dem[indx].max_west < max_west) - max_west = dem[indx].max_west; - } - } - - if (min_west == 360) - min_west = dem[indx].min_west; - - else { - if (fabs(dem[indx].min_west - min_west) < 180.0) { - if (dem[indx].min_west < min_west) - min_west = dem[indx].min_west; - } - - else { - if (dem[indx].min_west > min_west) - min_west = dem[indx].min_west; - } - } - - return 1; + if (debug == 1) { + fprintf(stderr, + "Loading \"%s\" into page %d...", + path_plus_name, indx + 1); + fflush(stderr); } - else - return -1; + if (fgets(line, 19, fd) != NULL) { + sscanf(line, "%f", &dem[indx].max_west); + } + + if (fgets(line, 19, fd) != NULL) { + sscanf(line, "%f", &dem[indx].min_north); + } + + if (fgets(line, 19, fd) != NULL) { + sscanf(line, "%f", &dem[indx].min_west); + } + + if (fgets(line, 19, fd) != NULL) { + sscanf(line, "%f", &dem[indx].max_north); + } + /* + Here X lines of DEM will be read until IPPD is reached. + Each .sdf tile contains 1200x1200 = 1.44M 'points' + Each point is sampled for 1200 resolution! + */ + for (x = 0; x < ippd; x++) { + for (y = 0; y < ippd; y++) { + + for (j = 0; j < jgets; j++) { + junk = fgets(jline, 19, fd); + } + + if (fgets(line, 19, fd) != NULL) { + data = atoi(line); + } + + dem[indx].data[x][y] = data; + dem[indx].signal[x][y] = 0; + dem[indx].mask[x][y] = 0; + + if (data > dem[indx].max_el) + dem[indx].max_el = data; + + if (data < dem[indx].min_el) + dem[indx].min_el = data; + + } + + if (ippd == 600) { + for (j = 0; j < IPPD; j++) { + junk = fgets(jline, 19, fd); + } + } + if (ippd == 300) { + for (j = 0; j < IPPD; j++) { + junk = fgets(jline, 19, fd); + junk = fgets(jline, 19, fd); + junk = fgets(jline, 19, fd); + + } + } + } + + fclose(fd); + + if (dem[indx].min_el < min_elevation) + min_elevation = dem[indx].min_el; + + if (dem[indx].max_el > max_elevation) + max_elevation = dem[indx].max_el; + + if (max_north == -90) + max_north = dem[indx].max_north; + + else if (dem[indx].max_north > max_north) + max_north = dem[indx].max_north; + + if (min_north == 90) + min_north = dem[indx].min_north; + + else if (dem[indx].min_north < min_north) + min_north = dem[indx].min_north; + + if (max_west == -1) + max_west = dem[indx].max_west; + + else { + if (abs(dem[indx].max_west - max_west) < 180) { + if (dem[indx].max_west > max_west) + max_west = dem[indx].max_west; + } + + else { + if (dem[indx].max_west < max_west) + max_west = dem[indx].max_west; + } + } + + if (min_west == 360) + min_west = dem[indx].min_west; + + else { + if (fabs(dem[indx].min_west - min_west) < 180.0) { + if (dem[indx].min_west < min_west) + min_west = dem[indx].min_west; + } + + else { + if (dem[indx].min_west > min_west) + min_west = dem[indx].min_west; + } + } + + return 1; } else @@ -557,7 +552,7 @@ char LoadSDF(char *name) /* If neither format can be found, then assume the area is water. */ - if (return_value == 0 || return_value == -1) { + if ( return_value == 0 || return_value < 0 ) { sscanf(name, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, From 0b495ad0946bb95f9ce31f7a1ad00d174311b051 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 18:55:47 +0000 Subject: [PATCH 04/12] Handle missing antenna pattern file --- inputs.cc | 536 +++++++++++++++++++++++++++--------------------------- inputs.hh | 2 +- main.cc | 5 +- 3 files changed, 272 insertions(+), 271 deletions(-) diff --git a/inputs.cc b/inputs.cc index a87703f..6d207dc 100644 --- a/inputs.cc +++ b/inputs.cc @@ -659,7 +659,7 @@ char LoadSDF(char *name) return return_value; } -void LoadPAT(char *filename) +int LoadPAT(char *filename) { /* This function reads and processes antenna pattern (.az and .el) files that correspond in name to previously @@ -696,38 +696,57 @@ void LoadPAT(char *filename) /* Load .az antenna pattern file */ - fd = fopen(azfile, "r"); + if( (fd = fopen(azfile, "r")) == NULL ) + return errno; - if (fd != NULL) { - /* Clear azimuth pattern array */ + /* Clear azimuth pattern array */ - for (x = 0; x <= 360; x++) { - azimuth[x] = 0.0; - read_count[x] = 0; + for (x = 0; x <= 360; x++) { + azimuth[x] = 0.0; + read_count[x] = 0; + } + + /* Read azimuth pattern rotation + in degrees measured clockwise + from true North. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Azimuth read error\n"); + //exit(0); + } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f", &rotation); + + /* Read azimuth (degrees) and corresponding + normalized field radiation pattern amplitude + (0.0 to 1.0) until EOF is reached. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Azimuth read error\n"); + //exit(0); + } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f %f", &az, &litude); + + do { + x = (int)rintf(az); + + if (x >= 0 && x <= 360 && fd != NULL) { + azimuth[x] += amplitude; + read_count[x]++; } - /* Read azimuth pattern rotation - in degrees measured clockwise - from true North. */ - if (fgets(string, 254, fd) == NULL) { //fprintf(stderr,"Azimuth read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f", &rotation); - - /* Read azimuth (degrees) and corresponding - normalized field radiation pattern amplitude - (0.0 to 1.0) until EOF is reached. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Azimuth read error\n"); - //exit(0); + // exit(0); } pointer = strchr(string, ';'); @@ -736,265 +755,244 @@ void LoadPAT(char *filename) sscanf(string, "%f %f", &az, &litude); - do { - x = (int)rintf(az); + } while (feof(fd) == 0); - if (x >= 0 && x <= 360 && fd != NULL) { - azimuth[x] += amplitude; - read_count[x]++; - } + fclose(fd); - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Azimuth read error\n"); - // exit(0); - } - pointer = strchr(string, ';'); + /* Handle 0=360 degree ambiguity */ - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &az, &litude); - - } while (feof(fd) == 0); - - fclose(fd); - - /* Handle 0=360 degree ambiguity */ - - if ((read_count[0] == 0) && (read_count[360] != 0)) { - read_count[0] = read_count[360]; - azimuth[0] = azimuth[360]; - } - - if ((read_count[0] != 0) && (read_count[360] == 0)) { - read_count[360] = read_count[0]; - azimuth[360] = azimuth[0]; - } - - /* Average pattern values in case more than - one was read for each degree of azimuth. */ - - for (x = 0; x <= 360; x++) { - if (read_count[x] > 1) - azimuth[x] /= (float)read_count[x]; - } - - /* Interpolate missing azimuths - to completely fill the array */ - - last_index = -1; - next_index = -1; - - for (x = 0; x <= 360; x++) { - if (read_count[x] != 0) { - if (last_index == -1) - last_index = x; - else - next_index = x; - } - - if (last_index != -1 && next_index != -1) { - valid1 = azimuth[last_index]; - valid2 = azimuth[next_index]; - - span = next_index - last_index; - delta = (valid2 - valid1) / (float)span; - - for (y = last_index + 1; y < next_index; y++) - azimuth[y] = azimuth[y - 1] + delta; - - last_index = y; - next_index = -1; - } - } - - /* Perform azimuth pattern rotation - and load azimuth_pattern[361] with - azimuth pattern data in its final form. */ - - for (x = 0; x < 360; x++) { - y = x + (int)rintf(rotation); - - if (y >= 360) - y -= 360; - - azimuth_pattern[y] = azimuth[x]; - } - - azimuth_pattern[360] = azimuth_pattern[0]; - - got_azimuth_pattern = 255; + if ((read_count[0] == 0) && (read_count[360] != 0)) { + read_count[0] = read_count[360]; + azimuth[0] = azimuth[360]; } + if ((read_count[0] != 0) && (read_count[360] == 0)) { + read_count[360] = read_count[0]; + azimuth[360] = azimuth[0]; + } + + /* Average pattern values in case more than + one was read for each degree of azimuth. */ + + for (x = 0; x <= 360; x++) { + if (read_count[x] > 1) + azimuth[x] /= (float)read_count[x]; + } + + /* Interpolate missing azimuths + to completely fill the array */ + + last_index = -1; + next_index = -1; + + for (x = 0; x <= 360; x++) { + if (read_count[x] != 0) { + if (last_index == -1) + last_index = x; + else + next_index = x; + } + + if (last_index != -1 && next_index != -1) { + valid1 = azimuth[last_index]; + valid2 = azimuth[next_index]; + + span = next_index - last_index; + delta = (valid2 - valid1) / (float)span; + + for (y = last_index + 1; y < next_index; y++) + azimuth[y] = azimuth[y - 1] + delta; + + last_index = y; + next_index = -1; + } + } + + /* Perform azimuth pattern rotation + and load azimuth_pattern[361] with + azimuth pattern data in its final form. */ + + for (x = 0; x < 360; x++) { + y = x + (int)rintf(rotation); + + if (y >= 360) + y -= 360; + + azimuth_pattern[y] = azimuth[x]; + } + + azimuth_pattern[360] = azimuth_pattern[0]; + + got_azimuth_pattern = 255; + /* Read and process .el file */ - fd = fopen(elfile, "r"); + if( (fd = fopen(elfile, "r")) == NULL ) + return errno; - if (fd != NULL) { - for (x = 0; x <= 10000; x++) { - el_pattern[x] = 0.0; - read_count[x] = 0; + for (x = 0; x <= 10000; x++) { + el_pattern[x] = 0.0; + read_count[x] = 0; + } + + /* Read mechanical tilt (degrees) and + tilt azimuth in degrees measured + clockwise from true North. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Tilt read error\n"); + //exit(0); + } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f %f", &mechanical_tilt, &tilt_azimuth); + + /* Read elevation (degrees) and corresponding + normalized field radiation pattern amplitude + (0.0 to 1.0) until EOF is reached. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Ant elevation read error\n"); + //exit(0); + } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f %f", &elevation, &litude); + + while (feof(fd) == 0) { + /* Read in normalized radiated field values + for every 0.01 degrees of elevation between + -10.0 and +90.0 degrees */ + + x = (int)rintf(100.0 * (elevation + 10.0)); + + if (x >= 0 && x <= 10000) { + el_pattern[x] += amplitude; + read_count[x]++; } - /* Read mechanical tilt (degrees) and - tilt azimuth in degrees measured - clockwise from true North. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Tilt read error\n"); - //exit(0); + if (fgets(string, 254, fd) != NULL) { + pointer = strchr(string, ';'); } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &mechanical_tilt, &tilt_azimuth); - - /* Read elevation (degrees) and corresponding - normalized field radiation pattern amplitude - (0.0 to 1.0) until EOF is reached. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Ant elevation read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - if (pointer != NULL) *pointer = 0; sscanf(string, "%f %f", &elevation, &litude); - - while (feof(fd) == 0) { - /* Read in normalized radiated field values - for every 0.01 degrees of elevation between - -10.0 and +90.0 degrees */ - - x = (int)rintf(100.0 * (elevation + 10.0)); - - if (x >= 0 && x <= 10000) { - el_pattern[x] += amplitude; - read_count[x]++; - } - - if (fgets(string, 254, fd) != NULL) { - pointer = strchr(string, ';'); - } - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &elevation, &litude); - } - - fclose(fd); - - /* Average the field values in case more than - one was read for each 0.01 degrees of elevation. */ - - for (x = 0; x <= 10000; x++) { - if (read_count[x] > 1) - el_pattern[x] /= (float)read_count[x]; - } - - /* Interpolate between missing elevations (if - any) to completely fill the array and provide - radiated field values for every 0.01 degrees of - elevation. */ - - last_index = -1; - next_index = -1; - - for (x = 0; x <= 10000; x++) { - if (read_count[x] != 0) { - if (last_index == -1) - last_index = x; - else - next_index = x; - } - - if (last_index != -1 && next_index != -1) { - valid1 = el_pattern[last_index]; - valid2 = el_pattern[next_index]; - - span = next_index - last_index; - delta = (valid2 - valid1) / (float)span; - - for (y = last_index + 1; y < next_index; y++) - el_pattern[y] = - el_pattern[y - 1] + delta; - - last_index = y; - next_index = -1; - } - } - - /* Fill slant_angle[] array with offset angles based - on the antenna's mechanical beam tilt (if any) - and tilt direction (azimuth). */ - - if (mechanical_tilt == 0.0) { - for (x = 0; x <= 360; x++) - slant_angle[x] = 0.0; - } - - else { - tilt_increment = mechanical_tilt / 90.0; - - for (x = 0; x <= 360; x++) { - xx = (float)x; - y = (int)rintf(tilt_azimuth + xx); - - while (y >= 360) - y -= 360; - - while (y < 0) - y += 360; - - if (x <= 180) - slant_angle[y] = - -(tilt_increment * (90.0 - xx)); - - if (x > 180) - slant_angle[y] = - -(tilt_increment * (xx - 270.0)); - } - } - - slant_angle[360] = slant_angle[0]; /* 360 degree wrap-around */ - - for (w = 0; w <= 360; w++) { - tilt = slant_angle[w]; - - /** Convert tilt angle to - an array index offset **/ - - y = (int)rintf(100.0 * tilt); - - /* Copy shifted el_pattern[10001] field - values into elevation_pattern[361][1001] - at the corresponding azimuth, downsampling - (averaging) along the way in chunks of 10. */ - - for (x = y, z = 0; z <= 1000; x += 10, z++) { - for (sum = 0.0, a = 0; a < 10; a++) { - b = a + x; - - if (b >= 0 && b <= 10000) - sum += el_pattern[b]; - if (b < 0) - sum += el_pattern[0]; - if (b > 10000) - sum += el_pattern[10000]; - } - - elevation_pattern[w][z] = sum / 10.0; - } - } - - got_elevation_pattern = 255; } + fclose(fd); + + /* Average the field values in case more than + one was read for each 0.01 degrees of elevation. */ + + for (x = 0; x <= 10000; x++) { + if (read_count[x] > 1) + el_pattern[x] /= (float)read_count[x]; + } + + /* Interpolate between missing elevations (if + any) to completely fill the array and provide + radiated field values for every 0.01 degrees of + elevation. */ + + last_index = -1; + next_index = -1; + + for (x = 0; x <= 10000; x++) { + if (read_count[x] != 0) { + if (last_index == -1) + last_index = x; + else + next_index = x; + } + + if (last_index != -1 && next_index != -1) { + valid1 = el_pattern[last_index]; + valid2 = el_pattern[next_index]; + + span = next_index - last_index; + delta = (valid2 - valid1) / (float)span; + + for (y = last_index + 1; y < next_index; y++) + el_pattern[y] = + el_pattern[y - 1] + delta; + + last_index = y; + next_index = -1; + } + } + + /* Fill slant_angle[] array with offset angles based + on the antenna's mechanical beam tilt (if any) + and tilt direction (azimuth). */ + + if (mechanical_tilt == 0.0) { + for (x = 0; x <= 360; x++) + slant_angle[x] = 0.0; + } + + else { + tilt_increment = mechanical_tilt / 90.0; + + for (x = 0; x <= 360; x++) { + xx = (float)x; + y = (int)rintf(tilt_azimuth + xx); + + while (y >= 360) + y -= 360; + + while (y < 0) + y += 360; + + if (x <= 180) + slant_angle[y] = + -(tilt_increment * (90.0 - xx)); + + if (x > 180) + slant_angle[y] = + -(tilt_increment * (xx - 270.0)); + } + } + + slant_angle[360] = slant_angle[0]; /* 360 degree wrap-around */ + + for (w = 0; w <= 360; w++) { + tilt = slant_angle[w]; + + /** Convert tilt angle to + an array index offset **/ + + y = (int)rintf(100.0 * tilt); + + /* Copy shifted el_pattern[10001] field + values into elevation_pattern[361][1001] + at the corresponding azimuth, downsampling + (averaging) along the way in chunks of 10. */ + + for (x = y, z = 0; z <= 1000; x += 10, z++) { + for (sum = 0.0, a = 0; a < 10; a++) { + b = a + x; + + if (b >= 0 && b <= 10000) + sum += el_pattern[b]; + if (b < 0) + sum += el_pattern[0]; + if (b > 10000) + sum += el_pattern[10000]; + } + + elevation_pattern[w][z] = sum / 10.0; + } + } + + got_elevation_pattern = 255; + for (x = 0; x <= 360; x++) { for (y = 0; y <= 1000; y++) { if (got_elevation_pattern) diff --git a/inputs.hh b/inputs.hh index eb0b086..e634737 100644 --- a/inputs.hh +++ b/inputs.hh @@ -5,7 +5,7 @@ int LoadSDF_SDF(char *name, int winfiles); char LoadSDF(char *name, int winfiles); -void LoadPAT(char *filename); +int LoadPAT(char *filename); void LoadSignalColors(struct site xmtr); void LoadLossColors(struct site xmtr); void LoadDBMColors(struct site xmtr); diff --git a/main.cc b/main.cc index 33f3173..74c4a6f 100644 --- a/main.cc +++ b/main.cc @@ -1218,7 +1218,10 @@ int main(int argc, char *argv[]) strncpy(mapfile, argv[z], 253); strncpy(tx_site[0].name, "Tx", 2); strncpy(tx_site[0].filename, argv[z], 253); - LoadPAT(argv[z]); + if( (result = LoadPAT(argv[z])) != 0 ){ + fprintf(stderr,"Error reading antenna pattern file\n"); + exit(result); + } } else if (z <= y && argv[z][0] && argv[z][0] == '-' && argv[z][1] == '\0' ) { /* Handle writing image data to stdout */ to_stdout = true; From 96257f9b16a738b2a0903243375ad731a733c14d Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 19:29:14 +0000 Subject: [PATCH 05/12] Detect perm errors in sig colors --- inputs.cc | 15 ++++++++------- inputs.hh | 2 +- main.cc | 4 ++-- outputs.cc | 7 +++++-- outputs.hh | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/inputs.cc b/inputs.cc index 6d207dc..45bd0c5 100644 --- a/inputs.cc +++ b/inputs.cc @@ -1008,9 +1008,10 @@ int LoadPAT(char *filename) LR.antenna_pattern[x][y] = az * elevation; } } + return 0; } -void LoadSignalColors(struct site xmtr) +int LoadSignalColors(struct site xmtr) { int x, y, ok, val[4]; char filename[255], string[80], *pointer = NULL, *s = NULL; @@ -1095,14 +1096,13 @@ void LoadSignalColors(struct site xmtr) region.levels = 13; - fd = fopen(filename, "r"); - - if (fd == NULL && xmtr.filename[0] == '\0') - /* Don't save if we don't have an output file */ - return; + /* Don't save if we don't have an output file */ + if ( xmtr.filename[0] == '\0' && (fd = fopen(filename, "r")) == NULL ) + return 0; if (fd == NULL) { - fd = fopen(filename, "w"); + if( (fd = fopen(filename, "w")) == NULL ) + return errno; for (x = 0; x < region.levels; x++) fprintf(fd, "%3d: %3d, %3d, %3d\n", region.level[x], @@ -1147,6 +1147,7 @@ void LoadSignalColors(struct site xmtr) fclose(fd); region.levels = x; } + return 0; } void LoadLossColors(struct site xmtr) diff --git a/inputs.hh b/inputs.hh index e634737..3f66472 100644 --- a/inputs.hh +++ b/inputs.hh @@ -6,7 +6,7 @@ int LoadSDF_SDF(char *name, int winfiles); char LoadSDF(char *name, int winfiles); int LoadPAT(char *filename); -void LoadSignalColors(struct site xmtr); +int LoadSignalColors(struct site xmtr); void LoadLossColors(struct site xmtr); void LoadDBMColors(struct site xmtr); void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); diff --git a/main.cc b/main.cc index 74c4a6f..dfc62a8 100644 --- a/main.cc +++ b/main.cc @@ -1846,8 +1846,8 @@ int main(int argc, char *argv[]) DoRxdPwr((to_stdout == true ? NULL : mapfile), geo, kml, ngs, tx_site, txsites); else - DoSigStr(mapfile, geo, kml, ngs, tx_site, - txsites); + if( (result = DoSigStr(mapfile, geo, kml, ngs, tx_site,txsites)) != 0 ) + return result; } if(lidar){ east=eastoffset; diff --git a/outputs.cc b/outputs.cc index ce2ba75..7f59063 100644 --- a/outputs.cc +++ b/outputs.cc @@ -256,7 +256,7 @@ void DoPathLoss(char *filename, unsigned char geo, unsigned char kml, } -void DoSigStr(char *filename, unsigned char geo, unsigned char kml, +int DoSigStr(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites) { /* This function generates a topographic map in Portable Pix Map @@ -284,7 +284,10 @@ void DoSigStr(char *filename, unsigned char geo, unsigned char kml, 255.0 / pow((double)(max_elevation - min_elevation), one_over_gamma); - LoadSignalColors(xmtr[0]); + if( (success = LoadSignalColors(xmtr[0])) != 0 ){ + fprintf(stderr,"Error loading signal colors\n"); + return success; + } if( filename != NULL ) { diff --git a/outputs.hh b/outputs.hh index ac334e4..2506292 100644 --- a/outputs.hh +++ b/outputs.hh @@ -3,7 +3,7 @@ void DoPathLoss(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites); -void DoSigStr(char *filename, unsigned char geo, unsigned char kml, +int DoSigStr(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites); void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites); From d33f5d293eb343c9cb29cceada6c8b1d49646032 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 19:35:15 +0000 Subject: [PATCH 06/12] Correctly detect perm errors on pat files --- inputs.cc | 532 +++++++++++++++++++++++++++--------------------------- 1 file changed, 268 insertions(+), 264 deletions(-) diff --git a/inputs.cc b/inputs.cc index 45bd0c5..0e64bf7 100644 --- a/inputs.cc +++ b/inputs.cc @@ -696,57 +696,37 @@ int LoadPAT(char *filename) /* Load .az antenna pattern file */ - if( (fd = fopen(azfile, "r")) == NULL ) - return errno; + if( (fd = fopen(azfile, "r")) != NULL ){ - /* Clear azimuth pattern array */ + /* Clear azimuth pattern array */ - for (x = 0; x <= 360; x++) { - azimuth[x] = 0.0; - read_count[x] = 0; - } - - /* Read azimuth pattern rotation - in degrees measured clockwise - from true North. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Azimuth read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f", &rotation); - - /* Read azimuth (degrees) and corresponding - normalized field radiation pattern amplitude - (0.0 to 1.0) until EOF is reached. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Azimuth read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &az, &litude); - - do { - x = (int)rintf(az); - - if (x >= 0 && x <= 360 && fd != NULL) { - azimuth[x] += amplitude; - read_count[x]++; + for (x = 0; x <= 360; x++) { + azimuth[x] = 0.0; + read_count[x] = 0; } + /* Read azimuth pattern rotation + in degrees measured clockwise + from true North. */ + if (fgets(string, 254, fd) == NULL) { //fprintf(stderr,"Azimuth read error\n"); - // exit(0); + //exit(0); + } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f", &rotation); + + /* Read azimuth (degrees) and corresponding + normalized field radiation pattern amplitude + (0.0 to 1.0) until EOF is reached. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Azimuth read error\n"); + //exit(0); } pointer = strchr(string, ';'); @@ -755,258 +735,282 @@ int LoadPAT(char *filename) sscanf(string, "%f %f", &az, &litude); - } while (feof(fd) == 0); + do { + x = (int)rintf(az); - fclose(fd); + if (x >= 0 && x <= 360 && fd != NULL) { + azimuth[x] += amplitude; + read_count[x]++; + } - /* Handle 0=360 degree ambiguity */ + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Azimuth read error\n"); + // exit(0); + } + pointer = strchr(string, ';'); - if ((read_count[0] == 0) && (read_count[360] != 0)) { - read_count[0] = read_count[360]; - azimuth[0] = azimuth[360]; - } + if (pointer != NULL) + *pointer = 0; - if ((read_count[0] != 0) && (read_count[360] == 0)) { - read_count[360] = read_count[0]; - azimuth[360] = azimuth[0]; - } + sscanf(string, "%f %f", &az, &litude); - /* Average pattern values in case more than - one was read for each degree of azimuth. */ + } while (feof(fd) == 0); - for (x = 0; x <= 360; x++) { - if (read_count[x] > 1) - azimuth[x] /= (float)read_count[x]; - } + fclose(fd); - /* Interpolate missing azimuths - to completely fill the array */ + /* Handle 0=360 degree ambiguity */ - last_index = -1; - next_index = -1; - - for (x = 0; x <= 360; x++) { - if (read_count[x] != 0) { - if (last_index == -1) - last_index = x; - else - next_index = x; + if ((read_count[0] == 0) && (read_count[360] != 0)) { + read_count[0] = read_count[360]; + azimuth[0] = azimuth[360]; } - if (last_index != -1 && next_index != -1) { - valid1 = azimuth[last_index]; - valid2 = azimuth[next_index]; - - span = next_index - last_index; - delta = (valid2 - valid1) / (float)span; - - for (y = last_index + 1; y < next_index; y++) - azimuth[y] = azimuth[y - 1] + delta; - - last_index = y; - next_index = -1; + if ((read_count[0] != 0) && (read_count[360] == 0)) { + read_count[360] = read_count[0]; + azimuth[360] = azimuth[0]; } + + /* Average pattern values in case more than + one was read for each degree of azimuth. */ + + for (x = 0; x <= 360; x++) { + if (read_count[x] > 1) + azimuth[x] /= (float)read_count[x]; + } + + /* Interpolate missing azimuths + to completely fill the array */ + + last_index = -1; + next_index = -1; + + for (x = 0; x <= 360; x++) { + if (read_count[x] != 0) { + if (last_index == -1) + last_index = x; + else + next_index = x; + } + + if (last_index != -1 && next_index != -1) { + valid1 = azimuth[last_index]; + valid2 = azimuth[next_index]; + + span = next_index - last_index; + delta = (valid2 - valid1) / (float)span; + + for (y = last_index + 1; y < next_index; y++) + azimuth[y] = azimuth[y - 1] + delta; + + last_index = y; + next_index = -1; + } + } + + /* Perform azimuth pattern rotation + and load azimuth_pattern[361] with + azimuth pattern data in its final form. */ + + for (x = 0; x < 360; x++) { + y = x + (int)rintf(rotation); + + if (y >= 360) + y -= 360; + + azimuth_pattern[y] = azimuth[x]; + } + + azimuth_pattern[360] = azimuth_pattern[0]; + + got_azimuth_pattern = 255; + }else if( errno == EACCES ){ + return errno; } - /* Perform azimuth pattern rotation - and load azimuth_pattern[361] with - azimuth pattern data in its final form. */ - - for (x = 0; x < 360; x++) { - y = x + (int)rintf(rotation); - - if (y >= 360) - y -= 360; - - azimuth_pattern[y] = azimuth[x]; - } - - azimuth_pattern[360] = azimuth_pattern[0]; - - got_azimuth_pattern = 255; - /* Read and process .el file */ - if( (fd = fopen(elfile, "r")) == NULL ) - return errno; + if( (fd = fopen(elfile, "r")) != NULL ){ - for (x = 0; x <= 10000; x++) { - el_pattern[x] = 0.0; - read_count[x] = 0; - } - - /* Read mechanical tilt (degrees) and - tilt azimuth in degrees measured - clockwise from true North. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Tilt read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &mechanical_tilt, &tilt_azimuth); - - /* Read elevation (degrees) and corresponding - normalized field radiation pattern amplitude - (0.0 to 1.0) until EOF is reached. */ - - if (fgets(string, 254, fd) == NULL) { - //fprintf(stderr,"Ant elevation read error\n"); - //exit(0); - } - pointer = strchr(string, ';'); - - if (pointer != NULL) - *pointer = 0; - - sscanf(string, "%f %f", &elevation, &litude); - - while (feof(fd) == 0) { - /* Read in normalized radiated field values - for every 0.01 degrees of elevation between - -10.0 and +90.0 degrees */ - - x = (int)rintf(100.0 * (elevation + 10.0)); - - if (x >= 0 && x <= 10000) { - el_pattern[x] += amplitude; - read_count[x]++; + for (x = 0; x <= 10000; x++) { + el_pattern[x] = 0.0; + read_count[x] = 0; } - if (fgets(string, 254, fd) != NULL) { - pointer = strchr(string, ';'); + /* Read mechanical tilt (degrees) and + tilt azimuth in degrees measured + clockwise from true North. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Tilt read error\n"); + //exit(0); } + pointer = strchr(string, ';'); + + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f %f", &mechanical_tilt, &tilt_azimuth); + + /* Read elevation (degrees) and corresponding + normalized field radiation pattern amplitude + (0.0 to 1.0) until EOF is reached. */ + + if (fgets(string, 254, fd) == NULL) { + //fprintf(stderr,"Ant elevation read error\n"); + //exit(0); + } + pointer = strchr(string, ';'); + if (pointer != NULL) *pointer = 0; sscanf(string, "%f %f", &elevation, &litude); - } - fclose(fd); + while (feof(fd) == 0) { + /* Read in normalized radiated field values + for every 0.01 degrees of elevation between + -10.0 and +90.0 degrees */ - /* Average the field values in case more than - one was read for each 0.01 degrees of elevation. */ + x = (int)rintf(100.0 * (elevation + 10.0)); - for (x = 0; x <= 10000; x++) { - if (read_count[x] > 1) - el_pattern[x] /= (float)read_count[x]; - } - - /* Interpolate between missing elevations (if - any) to completely fill the array and provide - radiated field values for every 0.01 degrees of - elevation. */ - - last_index = -1; - next_index = -1; - - for (x = 0; x <= 10000; x++) { - if (read_count[x] != 0) { - if (last_index == -1) - last_index = x; - else - next_index = x; - } - - if (last_index != -1 && next_index != -1) { - valid1 = el_pattern[last_index]; - valid2 = el_pattern[next_index]; - - span = next_index - last_index; - delta = (valid2 - valid1) / (float)span; - - for (y = last_index + 1; y < next_index; y++) - el_pattern[y] = - el_pattern[y - 1] + delta; - - last_index = y; - next_index = -1; - } - } - - /* Fill slant_angle[] array with offset angles based - on the antenna's mechanical beam tilt (if any) - and tilt direction (azimuth). */ - - if (mechanical_tilt == 0.0) { - for (x = 0; x <= 360; x++) - slant_angle[x] = 0.0; - } - - else { - tilt_increment = mechanical_tilt / 90.0; - - for (x = 0; x <= 360; x++) { - xx = (float)x; - y = (int)rintf(tilt_azimuth + xx); - - while (y >= 360) - y -= 360; - - while (y < 0) - y += 360; - - if (x <= 180) - slant_angle[y] = - -(tilt_increment * (90.0 - xx)); - - if (x > 180) - slant_angle[y] = - -(tilt_increment * (xx - 270.0)); - } - } - - slant_angle[360] = slant_angle[0]; /* 360 degree wrap-around */ - - for (w = 0; w <= 360; w++) { - tilt = slant_angle[w]; - - /** Convert tilt angle to - an array index offset **/ - - y = (int)rintf(100.0 * tilt); - - /* Copy shifted el_pattern[10001] field - values into elevation_pattern[361][1001] - at the corresponding azimuth, downsampling - (averaging) along the way in chunks of 10. */ - - for (x = y, z = 0; z <= 1000; x += 10, z++) { - for (sum = 0.0, a = 0; a < 10; a++) { - b = a + x; - - if (b >= 0 && b <= 10000) - sum += el_pattern[b]; - if (b < 0) - sum += el_pattern[0]; - if (b > 10000) - sum += el_pattern[10000]; + if (x >= 0 && x <= 10000) { + el_pattern[x] += amplitude; + read_count[x]++; } - elevation_pattern[w][z] = sum / 10.0; + if (fgets(string, 254, fd) != NULL) { + pointer = strchr(string, ';'); + } + if (pointer != NULL) + *pointer = 0; + + sscanf(string, "%f %f", &elevation, &litude); } - } - got_elevation_pattern = 255; + fclose(fd); - for (x = 0; x <= 360; x++) { - for (y = 0; y <= 1000; y++) { - if (got_elevation_pattern) - elevation = elevation_pattern[x][y]; - else - elevation = 1.0; + /* Average the field values in case more than + one was read for each 0.01 degrees of elevation. */ - if (got_azimuth_pattern) - az = azimuth_pattern[x]; - else - az = 1.0; - - LR.antenna_pattern[x][y] = az * elevation; + for (x = 0; x <= 10000; x++) { + if (read_count[x] > 1) + el_pattern[x] /= (float)read_count[x]; } + + /* Interpolate between missing elevations (if + any) to completely fill the array and provide + radiated field values for every 0.01 degrees of + elevation. */ + + last_index = -1; + next_index = -1; + + for (x = 0; x <= 10000; x++) { + if (read_count[x] != 0) { + if (last_index == -1) + last_index = x; + else + next_index = x; + } + + if (last_index != -1 && next_index != -1) { + valid1 = el_pattern[last_index]; + valid2 = el_pattern[next_index]; + + span = next_index - last_index; + delta = (valid2 - valid1) / (float)span; + + for (y = last_index + 1; y < next_index; y++) + el_pattern[y] = + el_pattern[y - 1] + delta; + + last_index = y; + next_index = -1; + } + } + + /* Fill slant_angle[] array with offset angles based + on the antenna's mechanical beam tilt (if any) + and tilt direction (azimuth). */ + + if (mechanical_tilt == 0.0) { + for (x = 0; x <= 360; x++) + slant_angle[x] = 0.0; + } + + else { + tilt_increment = mechanical_tilt / 90.0; + + for (x = 0; x <= 360; x++) { + xx = (float)x; + y = (int)rintf(tilt_azimuth + xx); + + while (y >= 360) + y -= 360; + + while (y < 0) + y += 360; + + if (x <= 180) + slant_angle[y] = + -(tilt_increment * (90.0 - xx)); + + if (x > 180) + slant_angle[y] = + -(tilt_increment * (xx - 270.0)); + } + } + + slant_angle[360] = slant_angle[0]; /* 360 degree wrap-around */ + + for (w = 0; w <= 360; w++) { + tilt = slant_angle[w]; + + /** Convert tilt angle to + an array index offset **/ + + y = (int)rintf(100.0 * tilt); + + /* Copy shifted el_pattern[10001] field + values into elevation_pattern[361][1001] + at the corresponding azimuth, downsampling + (averaging) along the way in chunks of 10. */ + + for (x = y, z = 0; z <= 1000; x += 10, z++) { + for (sum = 0.0, a = 0; a < 10; a++) { + b = a + x; + + if (b >= 0 && b <= 10000) + sum += el_pattern[b]; + if (b < 0) + sum += el_pattern[0]; + if (b > 10000) + sum += el_pattern[10000]; + } + + elevation_pattern[w][z] = sum / 10.0; + } + } + + got_elevation_pattern = 255; + + for (x = 0; x <= 360; x++) { + for (y = 0; y <= 1000; y++) { + if (got_elevation_pattern) + elevation = elevation_pattern[x][y]; + else + elevation = 1.0; + + if (got_azimuth_pattern) + az = azimuth_pattern[x]; + else + az = 1.0; + + LR.antenna_pattern[x][y] = az * elevation; + } + } + }else if( errno == EACCES ){ + return errno; } return 0; } From da275074a92b2b162ff45d42e1c9b8dde4894148 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Wed, 22 Feb 2017 22:24:32 +0000 Subject: [PATCH 07/12] Improve PAT loading logic --- inputs.cc | 35 ++++++++++++----------------------- inputs.hh | 5 ++++- main.cc | 21 +++++++++++++++++++-- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/inputs.cc b/inputs.cc index 0e64bf7..f5c0a9b 100644 --- a/inputs.cc +++ b/inputs.cc @@ -659,14 +659,14 @@ char LoadSDF(char *name) return return_value; } -int LoadPAT(char *filename) +int LoadPAT(char *az_filename, char *el_filename) { /* This function reads and processes antenna pattern (.az and .el) files that correspond in name to previously loaded ss .lrp files. */ int a, b, w, x, y, z, last_index, next_index, span; - char string[255], azfile[255], elfile[255], *pointer = NULL; + char string[255], *pointer = NULL; float az, xx, elevation, amplitude, rotation, valid1, valid2, delta, azimuth[361], azimuth_pattern[361], el_pattern[10001], elevation_pattern[361][1001], slant_angle[361], tilt, @@ -674,21 +674,6 @@ int LoadPAT(char *filename) FILE *fd = NULL; unsigned char read_count[10001]; - for (x = 0; filename[x] != '.' && filename[x] != 0 && x < 250; x++) { - azfile[x] = filename[x]; - elfile[x] = filename[x]; - } - - azfile[x] = '.'; - azfile[x + 1] = 'a'; - azfile[x + 2] = 'z'; - azfile[x + 3] = 0; - - elfile[x] = '.'; - elfile[x + 1] = 'e'; - elfile[x + 2] = 'l'; - elfile[x + 3] = 0; - rotation = 0.0; got_azimuth_pattern = 0; @@ -696,8 +681,11 @@ int LoadPAT(char *filename) /* Load .az antenna pattern file */ - if( (fd = fopen(azfile, "r")) != NULL ){ + if( az_filename != NULL && (fd = fopen(az_filename, "r")) == NULL && errno != ENOENT ) + /* Any error other than file not existing is an error */ + return errno; + if( fd != NULL ){ /* Clear azimuth pattern array */ for (x = 0; x <= 360; x++) { @@ -757,6 +745,7 @@ int LoadPAT(char *filename) } while (feof(fd) == 0); fclose(fd); + fd = NULL; /* Handle 0=360 degree ambiguity */ @@ -823,13 +812,15 @@ int LoadPAT(char *filename) azimuth_pattern[360] = azimuth_pattern[0]; got_azimuth_pattern = 255; - }else if( errno == EACCES ){ - return errno; } /* Read and process .el file */ - if( (fd = fopen(elfile, "r")) != NULL ){ + if( el_filename != NULL && (fd = fopen(el_filename, "r")) == NULL && errno != ENOENT ) + /* Any error other than file not existing is an error */ + return errno; + + if( fd != NULL ){ for (x = 0; x <= 10000; x++) { el_pattern[x] = 0.0; @@ -1009,8 +1000,6 @@ int LoadPAT(char *filename) LR.antenna_pattern[x][y] = az * elevation; } } - }else if( errno == EACCES ){ - return errno; } return 0; } diff --git a/inputs.hh b/inputs.hh index 3f66472..3c14514 100644 --- a/inputs.hh +++ b/inputs.hh @@ -5,7 +5,7 @@ int LoadSDF_SDF(char *name, int winfiles); char LoadSDF(char *name, int winfiles); -int LoadPAT(char *filename); +int LoadPAT(char *az_filename, char *el_filename); int LoadSignalColors(struct site xmtr); void LoadLossColors(struct site xmtr); void LoadDBMColors(struct site xmtr); @@ -14,4 +14,7 @@ void LoadUDT(char *filename); int loadLIDAR(char *filename); int loadClutter(char *filename, double radius, struct site tx); +static const char AZ_FILE_SUFFIX[] = ".az"; +static const char EL_FILE_SUFFIX[] = ".el"; + #endif /* _INPUTS_HH_ */ diff --git a/main.cc b/main.cc index dfc62a8..c96b966 100644 --- a/main.cc +++ b/main.cc @@ -1050,6 +1050,7 @@ int main(int argc, char *argv[]) 0, area_mode = 0, max_txsites, ngs = 0; char mapfile[255], udt_file[255], ano_filename[255], lidar_tiles[4096], clutter_file[255]; + char *az_filename, *el_filename; double altitude = 0.0, altitudeLR = 0.0, tx_range = 0.0, rx_range = 0.0, deg_range = 0.0, deg_limit = 0.0, deg_range_lon; @@ -1218,10 +1219,26 @@ int main(int argc, char *argv[]) strncpy(mapfile, argv[z], 253); strncpy(tx_site[0].name, "Tx", 2); strncpy(tx_site[0].filename, argv[z], 253); - if( (result = LoadPAT(argv[z])) != 0 ){ - fprintf(stderr,"Error reading antenna pattern file\n"); + /* Antenna pattern files have the same basic name as the output file + * but with a different extension. If they exist, load them now */ + if( (az_filename = (char*) calloc(strlen(argv[z]) + strlen(AZ_FILE_SUFFIX) + 1, sizeof(char))) == NULL ) + return ENOMEM; + strcpy(az_filename, argv[z]); + strcat(az_filename, AZ_FILE_SUFFIX); + if( (el_filename = (char*) calloc(strlen(argv[z]) + strlen(EL_FILE_SUFFIX) + 1, sizeof(char))) == NULL ){ + free(az_filename); + return ENOMEM; + } + strcpy(el_filename, argv[z]); + strcat(el_filename, EL_FILE_SUFFIX); + if( (result = LoadPAT(az_filename,el_filename)) != 0 ){ + fprintf(stderr,"Permissions error reading antenna pattern file\n"); + free(az_filename); + free(el_filename); exit(result); } + free(az_filename); + free(el_filename); } else if (z <= y && argv[z][0] && argv[z][0] == '-' && argv[z][1] == '\0' ) { /* Handle writing image data to stdout */ to_stdout = true; From 7fb07b1793208d7236d957ec0300bb0cc4c34cef Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Sat, 4 Mar 2017 19:08:12 +0000 Subject: [PATCH 08/12] Detect perm errors in loss colors --- inputs.cc | 12 ++++++------ inputs.hh | 2 +- outputs.cc | 7 +++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/inputs.cc b/inputs.cc index f5c0a9b..409abe0 100644 --- a/inputs.cc +++ b/inputs.cc @@ -1143,7 +1143,7 @@ int LoadSignalColors(struct site xmtr) return 0; } -void LoadLossColors(struct site xmtr) +int LoadLossColors(struct site xmtr) { int x, y, ok, val[4]; char filename[255], string[80], *pointer = NULL, *s = NULL; @@ -1243,14 +1243,13 @@ void LoadLossColors(struct site xmtr) region.levels = 16; - fd = fopen(filename, "r"); - - if (fd == NULL && xmtr.filename[0] == '\0') + if ( xmtr.filename[0] == '\0' && (fd = fopen(filename, "r")) == NULL ) /* Don't save if we don't have an output file */ - return; + return 0; if (fd == NULL) { - fd = fopen(filename, "w"); + if( (fd = fopen(filename, "w")) == NULL ) + return errno; for (x = 0; x < region.levels; x++) fprintf(fd, "%3d: %3d, %3d, %3d\n", region.level[x], @@ -1295,6 +1294,7 @@ void LoadLossColors(struct site xmtr) fclose(fd); region.levels = x; } + return 0; } void LoadDBMColors(struct site xmtr) diff --git a/inputs.hh b/inputs.hh index 3c14514..f216b65 100644 --- a/inputs.hh +++ b/inputs.hh @@ -7,7 +7,7 @@ int LoadSDF_SDF(char *name, int winfiles); char LoadSDF(char *name, int winfiles); int LoadPAT(char *az_filename, char *el_filename); int LoadSignalColors(struct site xmtr); -void LoadLossColors(struct site xmtr); +int LoadLossColors(struct site xmtr); void LoadDBMColors(struct site xmtr); void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); void LoadUDT(char *filename); diff --git a/outputs.cc b/outputs.cc index 7f59063..43b2fa9 100644 --- a/outputs.cc +++ b/outputs.cc @@ -34,7 +34,7 @@ void DoPathLoss(char *filename, unsigned char geo, unsigned char kml, image_ctx_t ctx; int success; - if((success = image_init(&ctx, width, (kml ? height : height + 30), IMAGE_RGB, IMAGE_DEFAULT)) != 0){ + if( (success = image_init(&ctx, width, (kml ? height : height + 30), IMAGE_RGB, IMAGE_DEFAULT)) != 0 ){ fprintf(stderr,"Error initializing image\n"); exit(success); } @@ -44,7 +44,10 @@ void DoPathLoss(char *filename, unsigned char geo, unsigned char kml, 255.0 / pow((double)(max_elevation - min_elevation), one_over_gamma); - LoadLossColors(xmtr[0]); + if( (success = LoadLossColors(xmtr[0])) != 0 ){ + fprintf(stderr,"Error loading loss colors\n"); + exit(success); + } if( filename != NULL ) { From af13a8d4bab5ba92b248f694ade4365b843adcf7 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Sat, 4 Mar 2017 19:13:37 +0000 Subject: [PATCH 09/12] Detect perm errors in DBM colors --- inputs.cc | 12 ++++++------ inputs.hh | 2 +- outputs.cc | 7 +++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/inputs.cc b/inputs.cc index 409abe0..92312da 100644 --- a/inputs.cc +++ b/inputs.cc @@ -1297,7 +1297,7 @@ int LoadLossColors(struct site xmtr) return 0; } -void LoadDBMColors(struct site xmtr) +int LoadDBMColors(struct site xmtr) { int x, y, ok, val[4]; char filename[255], string[80], *pointer = NULL, *s = NULL; @@ -1397,14 +1397,13 @@ void LoadDBMColors(struct site xmtr) region.levels = 16; - fd = fopen(filename, "r"); - - if (fd == NULL && xmtr.filename[0] == '\0') + if ( (fd = fopen(filename, "r")) == NULL && xmtr.filename[0] == '\0' ) /* Don't save if we don't have an output file */ - return; + return 0; if (fd == NULL) { - fd = fopen(filename, "w"); + if( (fd = fopen(filename, "w")) == NULL ) + return errno; for (x = 0; x < region.levels; x++) fprintf(fd, "%+4d: %3d, %3d, %3d\n", region.level[x], @@ -1456,6 +1455,7 @@ void LoadDBMColors(struct site xmtr) fclose(fd); region.levels = x; } + return 0; } void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) diff --git a/inputs.hh b/inputs.hh index f216b65..d15a87c 100644 --- a/inputs.hh +++ b/inputs.hh @@ -8,7 +8,7 @@ char LoadSDF(char *name, int winfiles); int LoadPAT(char *az_filename, char *el_filename); int LoadSignalColors(struct site xmtr); int LoadLossColors(struct site xmtr); -void LoadDBMColors(struct site xmtr); +int LoadDBMColors(struct site xmtr); void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); void LoadUDT(char *filename); int loadLIDAR(char *filename); diff --git a/outputs.cc b/outputs.cc index 43b2fa9..70e38e9 100644 --- a/outputs.cc +++ b/outputs.cc @@ -528,7 +528,7 @@ void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml, image_ctx_t ctx; int success; - if((success = image_init(&ctx, width, (kml ? height : height + 30), IMAGE_RGB, IMAGE_DEFAULT)) != 0){ + if( (success = image_init(&ctx, width, (kml ? height : height + 30), IMAGE_RGB, IMAGE_DEFAULT)) != 0 ){ fprintf(stderr,"Error initializing image\n"); exit(success); } @@ -538,7 +538,10 @@ void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml, 255.0 / pow((double)(max_elevation - min_elevation), one_over_gamma); - LoadDBMColors(xmtr[0]); + if( (success = LoadDBMColors(xmtr[0])) != 0 ){ + fprintf(stderr,"Error loading DBM colors\n"); + exit(success); + } if( filename != NULL ) { From f3029bb3cfed9e9727ef161ebaaa1e358ef72025 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Sat, 4 Mar 2017 19:35:03 +0000 Subject: [PATCH 10/12] Detect and handle errors in topo data --- inputs.cc | 22 ++++++++++++++-------- inputs.hh | 4 ++-- main.cc | 14 +++++++++++--- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/inputs.cc b/inputs.cc index 92312da..a18d7a8 100644 --- a/inputs.cc +++ b/inputs.cc @@ -364,8 +364,8 @@ int LoadSDF_SDF(char *name) /* Parse filename for minimum latitude and longitude values */ - sscanf(sdf_file, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, - &maxlon); + sscanf(sdf_file, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, + &maxlon); sdf_file[x] = '.'; @@ -533,7 +533,7 @@ int LoadSDF_SDF(char *name) return 0; } -char LoadSDF(char *name) +int LoadSDF(char *name) { /* This function loads the requested SDF file from the filesystem. It first tries to invoke the LoadSDF_SDF() function to load an @@ -555,8 +555,8 @@ char LoadSDF(char *name) if ( return_value == 0 || return_value < 0 ) { - sscanf(name, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, - &maxlon); + sscanf(name, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, + &maxlon); /* Is it already in memory? */ @@ -1458,12 +1458,13 @@ int LoadDBMColors(struct site xmtr) return 0; } -void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) +int LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) { /* This function loads the SDF files required to cover the limits of the region specified. */ int x, y, width, ymin, ymax; + int success; width = ReduceAngle(max_lon - min_lon); @@ -1495,7 +1496,9 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) snprintf(string, 16, "%d:%d:%d:%d", x, x + 1, ymin, ymax); - LoadSDF(string); + if( (success = LoadSDF(string)) < 0 ){ + return -success; + } } } @@ -1526,9 +1529,12 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) snprintf(string, 16, "%d:%d:%d:%d", x, x + 1, ymin, ymax); - LoadSDF(string); + if( (success = LoadSDF(string)) < 0 ){ + return -success; + } } } + return 0; } void LoadUDT(char *filename) diff --git a/inputs.hh b/inputs.hh index d15a87c..81addde 100644 --- a/inputs.hh +++ b/inputs.hh @@ -4,12 +4,12 @@ #include "common.h" int LoadSDF_SDF(char *name, int winfiles); -char LoadSDF(char *name, int winfiles); +int LoadSDF(char *name, int winfiles); int LoadPAT(char *az_filename, char *el_filename); int LoadSignalColors(struct site xmtr); int LoadLossColors(struct site xmtr); int LoadDBMColors(struct site xmtr); -void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); +int LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); void LoadUDT(char *filename); int loadLIDAR(char *filename); int loadClutter(char *filename, double radius, struct site tx); diff --git a/main.cc b/main.cc index c96b966..07ff094 100644 --- a/main.cc +++ b/main.cc @@ -1708,9 +1708,13 @@ int main(int argc, char *argv[]) }else{ // DEM first - LoadTopoData(max_lon, min_lon, max_lat, min_lat); + if( (result = LoadTopoData(max_lon, min_lon, max_lat, min_lat)) != 0 ){ + // This only fails on errors loading SDF tiles + fprintf(stderr, "Error loading topo data\n"); + return result; + } - if (area_mode || topomap) { + if (area_mode || topomap) { for (z = 0; z < txsites && z < max_txsites; z++) { /* "Ball park" estimates used to load any additional SDF files required to conduct this analysis. */ @@ -1793,7 +1797,11 @@ int main(int argc, char *argv[]) /* Load any additional SDF files, if required */ - LoadTopoData(max_lon, min_lon, max_lat, min_lat); + if( (result = LoadTopoData(max_lon, min_lon, max_lat, min_lat)) != 0 ){ + // This only fails on errors loading SDF tiles + fprintf(stderr, "Error loading topo data\n"); + return result; + } } ppd=(double)ippd; yppd=ppd; From 4109c6488f06c30443d73f377eed51a2b0cf060d Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Sat, 4 Mar 2017 20:14:41 +0000 Subject: [PATCH 11/12] Detect and handle errors in loading udt --- inputs.cc | 223 ++++++++++++++++++++++++++++------------------------- inputs.hh | 2 +- main.cc | 18 +++-- outputs.cc | 2 +- 4 files changed, 131 insertions(+), 114 deletions(-) diff --git a/inputs.cc b/inputs.cc index a18d7a8..0126068 100644 --- a/inputs.cc +++ b/inputs.cc @@ -1537,7 +1537,7 @@ int LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) return 0; } -void LoadUDT(char *filename) +int LoadUDT(char *filename) { /* This function reads a file containing User-Defined Terrain features for their addition to the digital elevation model @@ -1552,13 +1552,83 @@ void LoadUDT(char *filename) double latitude, longitude, height, tempheight; FILE *fd1 = NULL, *fd2 = NULL; - strcpy(tempname, "/tmp/XXXXXX\0"); + strcpy(tempname, "/tmp/XXXXXX"); - fd1 = fopen(filename, "r"); + if( (fd1 = fopen(filename, "r")) == NULL ) + return errno; - if (fd1 != NULL) { - fd = mkstemp(tempname); - fd2 = fopen(tempname, "w"); + if( (fd = mkstemp(tempname)) == -1 ) + return errno; + + if( (fd2 = fdopen(fd,"w")) == NULL ){ + fclose(fd1); + close(fd); + return errno; + } + + s = fgets(input, 78, fd1); + + pointer = strchr(input, ';'); + + if (pointer != NULL) + *pointer = 0; + + while (feof(fd1) == 0) { + /* Parse line for latitude, longitude, height */ + + for (x = 0, y = 0, z = 0; + x < 78 && input[x] != 0 && z < 3; x++) { + if (input[x] != ',' && y < 78) { + str[z][y] = input[x]; + y++; + } + + else { + str[z][y] = 0; + z++; + y = 0; + } + } + + latitude = ReadBearing(str[0]); + longitude = ReadBearing(str[1]); + + if (longitude < 0.0) + longitude += 360; + + /* Remove and/or from antenna height string */ + + for (i = 0; + str[2][i] != 13 && str[2][i] != 10 + && str[2][i] != 0; i++) ; + + str[2][i] = 0; + + /* The terrain feature may be expressed in either + feet or meters. If the letter 'M' or 'm' is + discovered in the string, then this is an + indication that the value given is expressed + in meters. Otherwise the height is interpreted + as being expressed in feet. */ + + for (i = 0; + str[2][i] != 'M' && str[2][i] != 'm' + && str[2][i] != 0 && i < 48; i++) ; + + if (str[2][i] == 'M' || str[2][i] == 'm') { + str[2][i] = 0; + height = rint(atof(str[2])); + } + + else { + str[2][i] = 0; + height = rint(METERS_PER_FOOT * atof(str[2])); + } + + if (height > 0.0) + fprintf(fd2, "%d, %d, %f\n", + (int)rint(latitude / dpp), + (int)rint(longitude / dpp), height); s = fgets(input, 78, fd1); @@ -1566,125 +1636,64 @@ void LoadUDT(char *filename) if (pointer != NULL) *pointer = 0; + } - while (feof(fd1) == 0) { - /* Parse line for latitude, longitude, height */ + fclose(fd1); + fclose(fd2); - for (x = 0, y = 0, z = 0; - x < 78 && input[x] != 0 && z < 3; x++) { - if (input[x] != ',' && y < 78) { - str[z][y] = input[x]; - y++; - } + if( (fd1 = fopen(tempname, "r")) == NULL ) + return errno; - else { - str[z][y] = 0; - z++; - y = 0; - } - } + if( (fd2 = fopen(tempname, "r")) == NULL ){ + fclose(fd1); + return errno; + } - latitude = ReadBearing(str[0]); - longitude = ReadBearing(str[1]); + y = 0; - if (longitude < 0.0) - longitude += 360; + n = fscanf(fd1, "%d, %d, %lf", &xpix, &ypix, &height); - /* Remove and/or from antenna height string */ + do { + x = 0; + z = 0; - for (i = 0; - str[2][i] != 13 && str[2][i] != 10 - && str[2][i] != 0; i++) ; + n = fscanf(fd2, "%d, %d, %lf", &tempxpix, &tempypix, + &tempheight); - str[2][i] = 0; + do { + if (x > y && xpix == tempxpix + && ypix == tempypix) { + z = 1; /* Dupe! */ - /* The terrain feature may be expressed in either - feet or meters. If the letter 'M' or 'm' is - discovered in the string, then this is an - indication that the value given is expressed - in meters. Otherwise the height is interpreted - as being expressed in feet. */ - - for (i = 0; - str[2][i] != 'M' && str[2][i] != 'm' - && str[2][i] != 0 && i < 48; i++) ; - - if (str[2][i] == 'M' || str[2][i] == 'm') { - str[2][i] = 0; - height = rint(atof(str[2])); + if (tempheight > height) + height = tempheight; } else { - str[2][i] = 0; - height = rint(METERS_PER_FOOT * atof(str[2])); + n = fscanf(fd2, "%d, %d, %lf", + &tempxpix, &tempypix, + &tempheight); + x++; } - if (height > 0.0) - fprintf(fd2, "%d, %d, %f\n", - (int)rint(latitude / dpp), - (int)rint(longitude / dpp), height); + } while (feof(fd2) == 0 && z == 0); - s = fgets(input, 78, fd1); - - pointer = strchr(input, ';'); - - if (pointer != NULL) - *pointer = 0; - } - - fclose(fd1); - fclose(fd2); - close(fd); - - fd1 = fopen(tempname, "r"); - fd2 = fopen(tempname, "r"); - - y = 0; + if (z == 0) + /* No duplicate found */ + //fprintf(stderr,"%lf, %lf \n",xpix*dpp, ypix*dpp); + fflush(stderr); + AddElevation(xpix * dpp, ypix * dpp, height, 1); + fflush(stderr); n = fscanf(fd1, "%d, %d, %lf", &xpix, &ypix, &height); + y++; - do { - x = 0; - z = 0; + rewind(fd2); - n = fscanf(fd2, "%d, %d, %lf", &tempxpix, &tempypix, - &tempheight); - - do { - if (x > y && xpix == tempxpix - && ypix == tempypix) { - z = 1; /* Dupe! */ - - if (tempheight > height) - height = tempheight; - } - - else { - n = fscanf(fd2, "%d, %d, %lf", - &tempxpix, &tempypix, - &tempheight); - x++; - } - - } while (feof(fd2) == 0 && z == 0); - - if (z == 0) - /* No duplicate found */ - //fprintf(stderr,"%lf, %lf \n",xpix*dpp, ypix*dpp); - fflush(stderr); - AddElevation(xpix * dpp, ypix * dpp, height, 1); - fflush(stderr); - - n = fscanf(fd1, "%d, %d, %lf", &xpix, &ypix, &height); - y++; - - rewind(fd2); - - } while (feof(fd1) == 0); - - fclose(fd1); - fclose(fd2); - unlink(tempname); - } + } while (feof(fd1) == 0); + fclose(fd1); + fclose(fd2); + unlink(tempname); + return 0; } diff --git a/inputs.hh b/inputs.hh index 81addde..c946286 100644 --- a/inputs.hh +++ b/inputs.hh @@ -10,7 +10,7 @@ int LoadSignalColors(struct site xmtr); int LoadLossColors(struct site xmtr); int LoadDBMColors(struct site xmtr); int LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); -void LoadUDT(char *filename); +int LoadUDT(char *filename); int loadLIDAR(char *filename); int loadClutter(char *filename, double radius, struct site tx); diff --git a/main.cc b/main.cc index 07ff094..36af101 100644 --- a/main.cc +++ b/main.cc @@ -28,6 +28,7 @@ double version = 3.02; #include #include #include +#include #include "common.h" #include "inputs.hh" @@ -1049,8 +1050,8 @@ int main(int argc, char *argv[]) unsigned char LRmap = 0, txsites = 0, topomap = 0, geo = 0, kml = 0, area_mode = 0, max_txsites, ngs = 0; - char mapfile[255], udt_file[255], ano_filename[255], lidar_tiles[4096], clutter_file[255]; - char *az_filename, *el_filename; + char mapfile[255], ano_filename[255], lidar_tiles[4096], clutter_file[255]; + char *az_filename, *el_filename, *udt_file = NULL; double altitude = 0.0, altitudeLR = 0.0, tx_range = 0.0, rx_range = 0.0, deg_range = 0.0, deg_limit = 0.0, deg_range_lon; @@ -1142,7 +1143,7 @@ int main(int argc, char *argv[]) forced_erp = -1.0; forced_freq = 0.0; sdf_path[0] = 0; - udt_file[0] = 0; + udt_file = NULL; path.length = 0; max_txsites = 30; fzone_clearance = 0.6; @@ -1488,10 +1489,14 @@ int main(int argc, char *argv[]) } - /*UDT*/ if (strcmp(argv[x], "-udt") == 0) { + /*UDT*/ + if (strcmp(argv[x], "-udt") == 0) { z = x + 1; if (z <= y && argv[z][0]) { + udt_file = (char*) calloc(PATH_MAX+1, sizeof(char)); + if( udt_file == NULL ) + return ENOMEM; strncpy(udt_file, argv[z], 253); } } @@ -1813,7 +1818,10 @@ int main(int argc, char *argv[]) mpi = ippd-1; // User defined clutter file - LoadUDT(udt_file); + if( udt_file != NULL && (result = LoadUDT(udt_file)) != 0 ){ + fprintf(stderr, "Error loading clutter file\n"); + return result; + } // Enrich with Clutter if(strlen(clutter_file) > 1){ diff --git a/outputs.cc b/outputs.cc index 70e38e9..54c1041 100644 --- a/outputs.cc +++ b/outputs.cc @@ -507,7 +507,7 @@ int DoSigStr(char *filename, unsigned char geo, unsigned char kml, fclose(fd); fd = NULL; } - + return 0; } void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml, From 169a0840ccb7d4ff98faca6f13ae3fb752e68f20 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Mon, 6 Mar 2017 13:45:04 +0000 Subject: [PATCH 12/12] Add error handling to LoadSDF --- inputs.cc | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/inputs.cc b/inputs.cc index 0126068..3cadf59 100644 --- a/inputs.cc +++ b/inputs.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include "common.h" #include "main.hh" @@ -349,11 +350,12 @@ int LoadSDF_SDF(char *name) containing digital elevation model data into memory. Elevation data, maximum and minimum elevations, and quadrangle limits are stored in the first available - dem[] structure. */ + dem[] structure. + NOTE: On error, this function returns a negative errno */ int x, y, data = 0, indx, minlat, minlon, maxlat, maxlon, j; char found, free_page = 0, line[20], jline[20], sdf_file[255], - path_plus_name[255], *junk = NULL; + path_plus_name[PATH_MAX]; FILE *fd; @@ -364,9 +366,8 @@ int LoadSDF_SDF(char *name) /* Parse filename for minimum latitude and longitude values */ - sscanf(sdf_file, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, - &maxlon); - + if( sscanf(sdf_file, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, &maxlon) != 4 ) + return -EINVAL; sdf_file[x] = '.'; sdf_file[x + 1] = 's'; @@ -398,14 +399,14 @@ int LoadSDF_SDF(char *name) if (free_page && found == 0 && indx >= 0 && indx < MAXPAGES) { /* Search for SDF file in current working directory first */ - strncpy(path_plus_name, sdf_file, 255); + strncpy(path_plus_name, sdf_file, sizeof(path_plus_name)-1); if( (fd = fopen(path_plus_name, "rb")) == NULL ){ /* Next, try loading SDF file from path specified in $HOME/.ss_path file or by -d argument */ - strncpy(path_plus_name, sdf_path, 255); - strncat(path_plus_name, sdf_file, 255); + strncpy(path_plus_name, sdf_path, sizeof(path_plus_name)-1); + strncat(path_plus_name, sdf_file, sizeof(path_plus_name)-1); if( (fd = fopen(path_plus_name, "rb")) == NULL ){ return -errno; } @@ -419,19 +420,23 @@ int LoadSDF_SDF(char *name) } if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].max_west); + if( sscanf(line, "%f", &dem[indx].max_west) == EOF ) + return -errno; } if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].min_north); + if( sscanf(line, "%f", &dem[indx].min_north) == EOF ) + return -errno; } if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].min_west); + if( sscanf(line, "%f", &dem[indx].min_west) == EOF ) + return -errno; } if (fgets(line, 19, fd) != NULL) { - sscanf(line, "%f", &dem[indx].max_north); + if( sscanf(line, "%f", &dem[indx].max_north) == EOF ) + return -errno; } /* Here X lines of DEM will be read until IPPD is reached. @@ -442,10 +447,11 @@ int LoadSDF_SDF(char *name) for (y = 0; y < ippd; y++) { for (j = 0; j < jgets; j++) { - junk = fgets(jline, 19, fd); + if( fgets(jline, sizeof(jline), fd) == NULL ) + return -EIO; } - if (fgets(line, 19, fd) != NULL) { + if (fgets(line, sizeof(line), fd) != NULL) { data = atoi(line); } @@ -463,15 +469,18 @@ int LoadSDF_SDF(char *name) if (ippd == 600) { for (j = 0; j < IPPD; j++) { - junk = fgets(jline, 19, fd); + if( fgets(jline, sizeof(jline), fd) == NULL ) + return -EIO; } } if (ippd == 300) { for (j = 0; j < IPPD; j++) { - junk = fgets(jline, 19, fd); - junk = fgets(jline, 19, fd); - junk = fgets(jline, 19, fd); - + if( fgets(jline, sizeof(jline), fd) == NULL ) + return -EIO; + if( fgets(jline, sizeof(jline), fd) == NULL ) + return -EIO; + if( fgets(jline, sizeof(jline), fd) == NULL ) + return -EIO; } } }