Files
Signal-Server/inputs.cc
2017-02-22 12:08:21 +00:00

1698 lines
37 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include "common.h"
#include "main.hh"
int loadClutter(char *filename, double radius, struct site tx)
{
/* This function reads a MODIS 17-class clutter file in ASCII Grid format.
The nominal heights it applies to each value, eg. 5 (Mixed forest) = 15m are
taken from ITU-R P.452-11.
It doesn't have it's own matrix, instead it boosts the DEM matrix like point clutter
AddElevation(lat, lon, height);
If tiles are standard 2880 x 3840 then cellsize is constant at 0.004166
*/
int x, y, z, result, h, w;
double clh, xll, yll, xur, yur, cellsize, cellsize2, xOffset, yOffset, lat, lon, i, j;
char line[50000];
char * pch;
FILE *fd;
if( (fd = fopen(filename, "rb")) == NULL)
return errno;
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 (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;
}
void readLIDAR(FILE *fd, int h, int w, int indx,double n, double e, double s, double west)
{
int x = 0, y = 0, reads = 0, a=0, b=0, avg=0, tWidth = 0, tHeight = 0;
char line[25000];
char *pch;
dem[indx].max_north=n;
dem[indx].min_west=e;
dem[indx].min_north=s;
dem[indx].max_west=west;
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 (dem[indx].max_west > max_west)
max_west = dem[indx].max_west;
if (dem[indx].min_west < min_west)
min_west = dem[indx].min_west;
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;
}
}
for (y = h-1; y > -1; y--) {
x = w-1;
if (fgets(line, 25000, fd) != NULL) {
pch = strtok(line, " "); // split line into values
while (pch != NULL && x > -1) {
if (atoi(pch) <= -9999)
pch = "0";
dem[indx].data[y][x] = atoi(pch);
dem[indx].signal[x][y] = 0;
dem[indx].mask[x][y] = 0;
if (atoi(pch) > dem[indx].max_el) {
dem[indx].max_el = atoi(pch);
max_elevation = atoi(pch);
}
if (atoi(pch) < dem[indx].min_el) {
dem[indx].min_el = atoi(pch);
min_elevation = dem[indx].min_el;
}
x--;
pch = strtok(NULL, " ");
}//while
} else {
fprintf(stderr, "LIDAR error @ x %d y %d indx %d\n",
x, y, indx);
}//if
}//for
}
int loadLIDAR(char *filenames)
{
char *filename;
char *files[100]; // 10x10 tiles
int x, y, indx = 0, fc = 0, hoffset = 0, voffset = 0, pos,
dem_alloced = 0;
double xll, yll, xur, yur, cellsize, avgCellsize;
char found, free_page = 0, jline[20], lid_file[255],
path_plus_name[255], *junk = NULL;
char line[25000];
char * pch;
double TO_DEG = (180 / PI);
FILE *fd;
// test for multiple files
filename = strtok(filenames, " ,");
while (filename != NULL) {
files[fc] = filename;
filename = strtok(NULL, " ,");
fc++;
}
while (indx < fc) {
if( (fd = fopen(files[indx], "rb")) == NULL )
return errno;
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 (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
}
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;
ippd=IPPD;
height = (unsigned)((max_north-min_north) / cellsize);
width = (unsigned)((max_west-min_west) / cellsize);
if (debug)
fprintf(stderr, "fc %d WIDTH %d HEIGHT %d ippd %d minN %.5f maxN %.5f minW %.5f maxW %.5f avgCellsize %.5f\n", fc, width, height, ippd,min_north,max_north,min_west,max_west,avgCellsize);
return 0;
}
int LoadSDF_SDF(char *name)
{
/* This function reads uncompressed ss Data Files (.sdf)
containing digital elevation model data into memory.
Elevation data, maximum and minimum elevations, and
quadrangle limits are stored in the first available
dem[] structure. */
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;
FILE *fd;
for (x = 0; name[x] != '.' && name[x] != 0 && x < 250; x++)
sdf_file[x] = name[x];
sdf_file[x] = 0;
/* Parse filename for minimum latitude and longitude values */
sscanf(sdf_file, "%d:%d:%d:%d", &minlat, &maxlat, &minlon,
&maxlon);
sdf_file[x] = '.';
sdf_file[x + 1] = 's';
sdf_file[x + 2] = 'd';
sdf_file[x + 3] = 'f';
sdf_file[x + 4] = 0;
/* Is it already in memory? */
for (indx = 0, found = 0; indx < MAXPAGES && found == 0; indx++) {
if (minlat == dem[indx].min_north
&& minlon == dem[indx].min_west
&& maxlat == dem[indx].max_north
&& maxlon == dem[indx].max_west)
found = 1;
}
/* Is room available to load it? */
if (found == 0) {
for (indx = 0, free_page = 0; indx < MAXPAGES && free_page == 0;
indx++)
if (dem[indx].max_north == -90)
free_page = 1;
}
indx--;
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);
fd = fopen(path_plus_name, "rb");
if (fd == 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 != 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;
}
else
return -1;
}
else
return 0;
}
char 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
uncompressed SDF file (since uncompressed files load slightly
faster). If that attempt fails, then it tries to load a
compressed SDF file by invoking the LoadSDF_BZ() function.
If that fails, then we can assume that no elevation data
exists for the region requested, and that the region
requested must be entirely over water. */
int x, y, indx, minlat, minlon, maxlat, maxlon;
char found, free_page = 0;
int return_value = -1;
return_value = LoadSDF_SDF(name);
/* If neither format can be found, then assume the area is water. */
if (return_value == 0 || return_value == -1) {
sscanf(name, "%d:%d:%d:%d", &minlat, &maxlat, &minlon,
&maxlon);
/* Is it already in memory? */
for (indx = 0, found = 0; indx < MAXPAGES && found == 0; indx++) {
if (minlat == dem[indx].min_north
&& minlon == dem[indx].min_west
&& maxlat == dem[indx].max_north
&& maxlon == dem[indx].max_west)
found = 1;
}
/* Is room available to load it? */
if (found == 0) {
for (indx = 0, free_page = 0;
indx < MAXPAGES && free_page == 0; indx++)
if (dem[indx].max_north == -90)
free_page = 1;
}
indx--;
if (free_page && found == 0 && indx >= 0 && indx < MAXPAGES) {
if (debug == 1) {
fprintf(stderr,
"Region \"%s\" assumed as sea-level into page %d...\n",
name, indx + 1);
fflush(stderr);
}
dem[indx].max_west = maxlon;
dem[indx].min_north = minlat;
dem[indx].min_west = minlon;
dem[indx].max_north = maxlat;
/* Fill DEM with sea-level topography */
for (x = 0; x < ippd; x++)
for (y = 0; y < ippd; y++) {
dem[indx].data[x][y] = 0;
dem[indx].signal[x][y] = 0;
dem[indx].mask[x][y] = 0;
if (dem[indx].min_el > 0)
dem[indx].min_el = 0;
}
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 (abs(dem[indx].min_west - min_west) < 180) {
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_value = 1;
}
}
return return_value;
}
void LoadPAT(char *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;
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,
mechanical_tilt = 0.0, tilt_azimuth, tilt_increment, sum;
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;
got_elevation_pattern = 0;
/* Load .az antenna pattern file */
fd = fopen(azfile, "r");
if (fd != NULL) {
/* 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, &amplitude);
do {
x = (int)rintf(az);
if (x >= 0 && x <= 360 && fd != NULL) {
azimuth[x] += amplitude;
read_count[x]++;
}
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, &amplitude);
} 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;
}
/* Read and process .el file */
fd = fopen(elfile, "r");
if (fd != 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, &amplitude);
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, &amplitude);
}
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)
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;
}
}
}
void LoadSignalColors(struct site xmtr)
{
int x, y, ok, val[4];
char filename[255], string[80], *pointer = NULL, *s = NULL;
FILE *fd = NULL;
for (x = 0; xmtr.filename[x] != '.' && xmtr.filename[x] != 0 && x < 250;
x++)
filename[x] = xmtr.filename[x];
filename[x] = '.';
filename[x + 1] = 's';
filename[x + 2] = 'c';
filename[x + 3] = 'f';
filename[x + 4] = 0;
/* Default values */
region.level[0] = 128;
region.color[0][0] = 255;
region.color[0][1] = 0;
region.color[0][2] = 0;
region.level[1] = 118;
region.color[1][0] = 255;
region.color[1][1] = 165;
region.color[1][2] = 0;
region.level[2] = 108;
region.color[2][0] = 255;
region.color[2][1] = 206;
region.color[2][2] = 0;
region.level[3] = 98;
region.color[3][0] = 255;
region.color[3][1] = 255;
region.color[3][2] = 0;
region.level[4] = 88;
region.color[4][0] = 184;
region.color[4][1] = 255;
region.color[4][2] = 0;
region.level[5] = 78;
region.color[5][0] = 0;
region.color[5][1] = 255;
region.color[5][2] = 0;
region.level[6] = 68;
region.color[6][0] = 0;
region.color[6][1] = 208;
region.color[6][2] = 0;
region.level[7] = 58;
region.color[7][0] = 0;
region.color[7][1] = 196;
region.color[7][2] = 196;
region.level[8] = 48;
region.color[8][0] = 0;
region.color[8][1] = 148;
region.color[8][2] = 255;
region.level[9] = 38;
region.color[9][0] = 80;
region.color[9][1] = 80;
region.color[9][2] = 255;
region.level[10] = 28;
region.color[10][0] = 0;
region.color[10][1] = 38;
region.color[10][2] = 255;
region.level[11] = 18;
region.color[11][0] = 142;
region.color[11][1] = 63;
region.color[11][2] = 255;
region.level[12] = 8;
region.color[12][0] = 140;
region.color[12][1] = 0;
region.color[12][2] = 128;
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;
if (fd == NULL) {
fd = fopen(filename, "w");
for (x = 0; x < region.levels; x++)
fprintf(fd, "%3d: %3d, %3d, %3d\n", region.level[x],
region.color[x][0], region.color[x][1],
region.color[x][2]);
fclose(fd);
}
else {
x = 0;
s = fgets(string, 80, fd);
while (x < 128 && feof(fd) == 0) {
pointer = strchr(string, ';');
if (pointer != NULL)
*pointer = 0;
ok = sscanf(string, "%d: %d, %d, %d", &val[0], &val[1],
&val[2], &val[3]);
if (ok == 4) {
for (y = 0; y < 4; y++) {
if (val[y] > 255)
val[y] = 255;
if (val[y] < 0)
val[y] = 0;
}
region.level[x] = val[0];
region.color[x][0] = val[1];
region.color[x][1] = val[2];
region.color[x][2] = val[3];
x++;
}
s = fgets(string, 80, fd);
}
fclose(fd);
region.levels = x;
}
}
void LoadLossColors(struct site xmtr)
{
int x, y, ok, val[4];
char filename[255], string[80], *pointer = NULL, *s = NULL;
FILE *fd = NULL;
for (x = 0; xmtr.filename[x] != '.' && xmtr.filename[x] != 0 && x < 250;
x++)
filename[x] = xmtr.filename[x];
filename[x] = '.';
filename[x + 1] = 'l';
filename[x + 2] = 'c';
filename[x + 3] = 'f';
filename[x + 4] = 0;
/* Default values */
region.level[0] = 80;
region.color[0][0] = 255;
region.color[0][1] = 0;
region.color[0][2] = 0;
region.level[1] = 90;
region.color[1][0] = 255;
region.color[1][1] = 128;
region.color[1][2] = 0;
region.level[2] = 100;
region.color[2][0] = 255;
region.color[2][1] = 165;
region.color[2][2] = 0;
region.level[3] = 110;
region.color[3][0] = 255;
region.color[3][1] = 206;
region.color[3][2] = 0;
region.level[4] = 120;
region.color[4][0] = 255;
region.color[4][1] = 255;
region.color[4][2] = 0;
region.level[5] = 130;
region.color[5][0] = 184;
region.color[5][1] = 255;
region.color[5][2] = 0;
region.level[6] = 140;
region.color[6][0] = 0;
region.color[6][1] = 255;
region.color[6][2] = 0;
region.level[7] = 150;
region.color[7][0] = 0;
region.color[7][1] = 208;
region.color[7][2] = 0;
region.level[8] = 160;
region.color[8][0] = 0;
region.color[8][1] = 196;
region.color[8][2] = 196;
region.level[9] = 170;
region.color[9][0] = 0;
region.color[9][1] = 148;
region.color[9][2] = 255;
region.level[10] = 180;
region.color[10][0] = 80;
region.color[10][1] = 80;
region.color[10][2] = 255;
region.level[11] = 190;
region.color[11][0] = 0;
region.color[11][1] = 38;
region.color[11][2] = 255;
region.level[12] = 200;
region.color[12][0] = 142;
region.color[12][1] = 63;
region.color[12][2] = 255;
region.level[13] = 210;
region.color[13][0] = 196;
region.color[13][1] = 54;
region.color[13][2] = 255;
region.level[14] = 220;
region.color[14][0] = 255;
region.color[14][1] = 0;
region.color[14][2] = 255;
region.level[15] = 230;
region.color[15][0] = 255;
region.color[15][1] = 194;
region.color[15][2] = 204;
region.levels = 16;
fd = fopen(filename, "r");
if (fd == NULL && xmtr.filename[0] == '\0')
/* Don't save if we don't have an output file */
return;
if (fd == NULL) {
fd = fopen(filename, "w");
for (x = 0; x < region.levels; x++)
fprintf(fd, "%3d: %3d, %3d, %3d\n", region.level[x],
region.color[x][0], region.color[x][1],
region.color[x][2]);
fclose(fd);
}
else {
x = 0;
s = fgets(string, 80, fd);
while (x < 128 && feof(fd) == 0) {
pointer = strchr(string, ';');
if (pointer != NULL)
*pointer = 0;
ok = sscanf(string, "%d: %d, %d, %d", &val[0], &val[1],
&val[2], &val[3]);
if (ok == 4) {
for (y = 0; y < 4; y++) {
if (val[y] > 255)
val[y] = 255;
if (val[y] < 0)
val[y] = 0;
}
region.level[x] = val[0];
region.color[x][0] = val[1];
region.color[x][1] = val[2];
region.color[x][2] = val[3];
x++;
}
s = fgets(string, 80, fd);
}
fclose(fd);
region.levels = x;
}
}
void LoadDBMColors(struct site xmtr)
{
int x, y, ok, val[4];
char filename[255], string[80], *pointer = NULL, *s = NULL;
FILE *fd = NULL;
for (x = 0; xmtr.filename[x] != '.' && xmtr.filename[x] != 0 && x < 250;
x++)
filename[x] = xmtr.filename[x];
filename[x] = '.';
filename[x + 1] = 'd';
filename[x + 2] = 'c';
filename[x + 3] = 'f';
filename[x + 4] = 0;
/* Default values */
region.level[0] = 0;
region.color[0][0] = 255;
region.color[0][1] = 0;
region.color[0][2] = 0;
region.level[1] = -10;
region.color[1][0] = 255;
region.color[1][1] = 128;
region.color[1][2] = 0;
region.level[2] = -20;
region.color[2][0] = 255;
region.color[2][1] = 165;
region.color[2][2] = 0;
region.level[3] = -30;
region.color[3][0] = 255;
region.color[3][1] = 206;
region.color[3][2] = 0;
region.level[4] = -40;
region.color[4][0] = 255;
region.color[4][1] = 255;
region.color[4][2] = 0;
region.level[5] = -50;
region.color[5][0] = 184;
region.color[5][1] = 255;
region.color[5][2] = 0;
region.level[6] = -60;
region.color[6][0] = 0;
region.color[6][1] = 255;
region.color[6][2] = 0;
region.level[7] = -70;
region.color[7][0] = 0;
region.color[7][1] = 208;
region.color[7][2] = 0;
region.level[8] = -80;
region.color[8][0] = 0;
region.color[8][1] = 196;
region.color[8][2] = 196;
region.level[9] = -90;
region.color[9][0] = 0;
region.color[9][1] = 148;
region.color[9][2] = 255;
region.level[10] = -100;
region.color[10][0] = 80;
region.color[10][1] = 80;
region.color[10][2] = 255;
region.level[11] = -110;
region.color[11][0] = 0;
region.color[11][1] = 38;
region.color[11][2] = 255;
region.level[12] = -120;
region.color[12][0] = 142;
region.color[12][1] = 63;
region.color[12][2] = 255;
region.level[13] = -130;
region.color[13][0] = 196;
region.color[13][1] = 54;
region.color[13][2] = 255;
region.level[14] = -140;
region.color[14][0] = 255;
region.color[14][1] = 0;
region.color[14][2] = 255;
region.level[15] = -150;
region.color[15][0] = 255;
region.color[15][1] = 194;
region.color[15][2] = 204;
region.levels = 16;
fd = fopen(filename, "r");
if (fd == NULL && xmtr.filename[0] == '\0')
/* Don't save if we don't have an output file */
return;
if (fd == NULL) {
fd = fopen(filename, "w");
for (x = 0; x < region.levels; x++)
fprintf(fd, "%+4d: %3d, %3d, %3d\n", region.level[x],
region.color[x][0], region.color[x][1],
region.color[x][2]);
fclose(fd);
}
else {
x = 0;
s = fgets(string, 80, fd);
while (x < 128 && feof(fd) == 0) {
pointer = strchr(string, ';');
if (pointer != NULL)
*pointer = 0;
ok = sscanf(string, "%d: %d, %d, %d", &val[0], &val[1],
&val[2], &val[3]);
if (ok == 4) {
if (val[0] < -200)
val[0] = -200;
if (val[0] > +40)
val[0] = +40;
region.level[x] = val[0];
for (y = 1; y < 4; y++) {
if (val[y] > 255)
val[y] = 255;
if (val[y] < 0)
val[y] = 0;
}
region.color[x][0] = val[1];
region.color[x][1] = val[2];
region.color[x][2] = val[3];
x++;
}
s = fgets(string, 80, fd);
}
fclose(fd);
region.levels = x;
}
}
void 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;
width = ReduceAngle(max_lon - min_lon);
if ((max_lon - min_lon) <= 180.0) {
for (y = 0; y <= width; y++)
for (x = min_lat; x <= max_lat; x++) {
ymin = (int)(min_lon + (double)y);
while (ymin < 0)
ymin += 360;
while (ymin >= 360)
ymin -= 360;
ymax = ymin + 1;
while (ymax < 0)
ymax += 360;
while (ymax >= 360)
ymax -= 360;
if (ippd == 3600)
snprintf(string, 19,
"%d:%d:%d:%d-hd", x,
x + 1, ymin, ymax);
else
snprintf(string, 16,
"%d:%d:%d:%d", x,
x + 1, ymin, ymax);
LoadSDF(string);
}
}
else {
for (y = 0; y <= width; y++)
for (x = min_lat; x <= max_lat; x++) {
ymin = max_lon + y;
while (ymin < 0)
ymin += 360;
while (ymin >= 360)
ymin -= 360;
ymax = ymin + 1;
while (ymax < 0)
ymax += 360;
while (ymax >= 360)
ymax -= 360;
if (ippd == 3600)
snprintf(string, 19,
"%d:%d:%d:%d-hd", x,
x + 1, ymin, ymax);
else
snprintf(string, 16,
"%d:%d:%d:%d", x,
x + 1, ymin, ymax);
LoadSDF(string);
}
}
}
void LoadUDT(char *filename)
{
/* This function reads a file containing User-Defined Terrain
features for their addition to the digital elevation model
data used by SPLAT!. Elevations in the UDT file are evaluated
and then copied into a temporary file under /tmp. Then the
contents of the temp file are scanned, and if found to be unique,
are added to the ground elevations described by the digital
elevation data already loaded into memory. */
int i, x, y, z, ypix, xpix, tempxpix, tempypix, fd = 0, n = 0;
char input[80], str[3][80], tempname[15], *pointer = NULL, *s = NULL;
double latitude, longitude, height, tempheight;
FILE *fd1 = NULL, *fd2 = NULL;
strcpy(tempname, "/tmp/XXXXXX\0");
fd1 = fopen(filename, "r");
if (fd1 != NULL) {
fd = mkstemp(tempname);
fd2 = fopen(tempname, "w");
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 <CR> and/or <LF> 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);
pointer = strchr(input, ';');
if (pointer != NULL)
*pointer = 0;
}
fclose(fd1);
fclose(fd2);
close(fd);
fd1 = fopen(tempname, "r");
fd2 = fopen(tempname, "r");
y = 0;
n = fscanf(fd1, "%d, %d, %lf", &xpix, &ypix, &height);
do {
x = 0;
z = 0;
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);
}
}