forked from ExternalVendorCode/Signal-Server
v2.6 +multi-threading
This commit is contained in:
448
models/los.cc
448
models/los.cc
@@ -1,8 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../main.hh"
|
||||
#include "los.hh"
|
||||
#include "cost.hh"
|
||||
#include "ecc33.hh"
|
||||
#include "ericsson.hh"
|
||||
@@ -10,6 +10,154 @@
|
||||
#include "hata.hh"
|
||||
#include "itwom3.0.hh"
|
||||
#include "sui.hh"
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAXPAGES 64
|
||||
#define IPPD 3600
|
||||
#define NUM_SECTIONS 4
|
||||
|
||||
namespace {
|
||||
pthread_t threads[NUM_SECTIONS];
|
||||
unsigned int thread_count = 0;
|
||||
pthread_mutex_t maskMutex;
|
||||
|
||||
bool processed[MAXPAGES][IPPD][IPPD];
|
||||
bool has_init_processed = false;
|
||||
|
||||
struct propagationRange {
|
||||
int min_west, max_west, min_north, max_north;
|
||||
double altitude;
|
||||
bool eastwest, los, use_threads;
|
||||
site source;
|
||||
unsigned char mask_value;
|
||||
FILE *fd;
|
||||
int propmodel, knifeedge, pmenv;
|
||||
};
|
||||
|
||||
void* rangePropagation(void *parameters)
|
||||
{
|
||||
propagationRange *v = (propagationRange*)parameters;
|
||||
if(v->use_threads) {
|
||||
alloc_elev();
|
||||
alloc_path();
|
||||
}
|
||||
|
||||
double minwest = dpp + (double)v->min_west;
|
||||
double lon = v->eastwest ? minwest : v->min_west;
|
||||
double lat = v->min_north;
|
||||
int y = 0;
|
||||
|
||||
do {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
site edge;
|
||||
edge.lat = lat;
|
||||
edge.lon = lon;
|
||||
edge.alt = v->altitude;
|
||||
|
||||
if(v->los)
|
||||
PlotLOSPath(v->source, edge, v->mask_value, v->fd);
|
||||
else
|
||||
PlotPropPath(v->source, edge, v->mask_value, v->fd, v->propmodel,
|
||||
v->knifeedge, v->pmenv);
|
||||
|
||||
++y;
|
||||
if(v->eastwest)
|
||||
lon = minwest + (dpp * (double)y);
|
||||
else
|
||||
lat = (double)v->min_north + (dpp * (double)y);
|
||||
|
||||
|
||||
} while ( v->eastwest
|
||||
? (LonDiff(lon, (double)v->max_west) <= 0.0)
|
||||
: (lat < (double)v->max_north) );
|
||||
|
||||
if(v->use_threads) {
|
||||
free_elev();
|
||||
free_path();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_processed()
|
||||
{
|
||||
for(int i = 0; i < MAXPAGES; i++) {
|
||||
for (int x = 0; x < ippd; x++) {
|
||||
for (int y = 0; y < ippd; y++) {
|
||||
processed[i][x][y] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool can_process(double lat, double lon)
|
||||
{
|
||||
/* Lines, text, markings, and coverage areas are stored in a
|
||||
mask that is combined with topology data when topographic
|
||||
maps are generated by ss. This function sets bits in
|
||||
the mask based on the latitude and longitude of the area
|
||||
pointed to. */
|
||||
|
||||
int x, y, indx;
|
||||
char found;
|
||||
bool rtn = false;
|
||||
|
||||
for (indx = 0, found = 0; indx < MAXPAGES && found == 0;) {
|
||||
x = (int)rint(ppd * (lat - dem[indx].min_north));
|
||||
y = mpi - (int)rint(ppd * (LonDiff(dem[indx].max_west, lon)));
|
||||
|
||||
if (x >= 0 && x <= mpi && y >= 0 && y <= mpi)
|
||||
found = 1;
|
||||
else
|
||||
indx++;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/* As long as we only set this without resetting it we can
|
||||
check outside a mutex first without worrying about race
|
||||
conditions. But we must lock the mutex before updating the
|
||||
value. */
|
||||
|
||||
if(!processed[indx][x][y]) {
|
||||
pthread_mutex_lock(&maskMutex);
|
||||
|
||||
if(!processed[indx][x][y]) {
|
||||
rtn = true;
|
||||
processed[indx][x][y] = true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&maskMutex);
|
||||
}
|
||||
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void beginThread(void *arg)
|
||||
{
|
||||
if(!has_init_processed)
|
||||
init_processed();
|
||||
|
||||
int rc = pthread_create(&threads[thread_count], NULL, rangePropagation, arg);
|
||||
if (rc)
|
||||
printf("ERROR; return code from pthread_create() is %d\n", rc);
|
||||
else
|
||||
++thread_count;
|
||||
}
|
||||
|
||||
void finishThreads()
|
||||
{
|
||||
void* status;
|
||||
for(unsigned int i=0; i<thread_count; i++) {
|
||||
int rc = pthread_join(threads[i], &status);
|
||||
if (rc)
|
||||
printf("ERROR; return code from pthread_join() is %d\n", rc);
|
||||
}
|
||||
thread_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Acute Angle from Rx point to an obstacle of height (opp) and
|
||||
@@ -89,7 +237,9 @@ void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||
/* Test this point only if it hasn't been already
|
||||
tested and found to be free of obstructions. */
|
||||
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0) {
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0
|
||||
&& can_process(path.lat[y], path.lon[y])) {
|
||||
|
||||
distance = 5280.0 * path.distance[y];
|
||||
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||
rx_alt =
|
||||
@@ -183,8 +333,12 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
/* Process this point only if it
|
||||
has not already been processed. */
|
||||
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & 248) !=
|
||||
(mask_value << 3)) {
|
||||
if ( (GetMask(path.lat[y], path.lon[y]) & 248) !=
|
||||
(mask_value << 3) && can_process(path.lat[y], path.lon[y])) {
|
||||
|
||||
char fd_buffer[64];
|
||||
int buffer_offset = 0;
|
||||
|
||||
distance = 5280.0 * path.distance[y];
|
||||
xmtr_alt =
|
||||
four_thirds_earth + source.alt + path.elevation[0];
|
||||
@@ -337,6 +491,7 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
destination.alt *
|
||||
METERS_PER_FOOT, LR.eps_dielect,
|
||||
LR.sgm_conductivity,
|
||||
|
||||
LR.eno_ns_surfref, LR.frq_mhz,
|
||||
LR.radio_climate, LR.pol,
|
||||
LR.conf, LR.rel, loss, strmode,
|
||||
@@ -364,7 +519,7 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
loss, strmode, errnum);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (knifeedge == 1) {
|
||||
diffloss =
|
||||
ked(LR.frq_mhz,
|
||||
@@ -379,7 +534,8 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
azimuth = (Azimuth(source, temp));
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.7f, %.7f, %.3f, %.3f, ",
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.7f, %.7f, %.3f, %.3f, ",
|
||||
path.lat[y], path.lon[y], azimuth,
|
||||
elevation);
|
||||
|
||||
@@ -388,7 +544,8 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
or received power level (below), as appropriate. */
|
||||
|
||||
if (fd != NULL && LR.erp == 0.0)
|
||||
fprintf(fd, "%.2f", loss);
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.2f", loss);
|
||||
|
||||
/* Integrate the antenna's radiation
|
||||
pattern into the overall path loss. */
|
||||
@@ -418,7 +575,8 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
dBm = 10.0 * (log10(rxp * 1000.0));
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.3f", dBm);
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.3f", dBm);
|
||||
|
||||
/* Scale roughly between 0 and 255 */
|
||||
|
||||
@@ -466,7 +624,8 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
(unsigned char)ifs);
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.3f",
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.3f",
|
||||
field_strength);
|
||||
}
|
||||
}
|
||||
@@ -476,7 +635,7 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
ifs = 255;
|
||||
else
|
||||
ifs = (int)rint(loss);
|
||||
|
||||
|
||||
ofs = GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs < ifs && ofs != 0)
|
||||
@@ -488,9 +647,9 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
|
||||
if (fd != NULL) {
|
||||
if (block)
|
||||
fprintf(fd, " *");
|
||||
|
||||
fprintf(fd, "\n");
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
" *");
|
||||
fprintf(fd, "%s\n", fd_buffer);
|
||||
}
|
||||
|
||||
/* Mark this point as having been analyzed */
|
||||
@@ -503,7 +662,8 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
|
||||
}
|
||||
|
||||
void PlotLOSMap(struct site source, double altitude, char *plo_filename)
|
||||
void PlotLOSMap(struct site source, double altitude, char *plo_filename,
|
||||
bool use_threads)
|
||||
{
|
||||
/* This function performs a 360 degree sweep around the
|
||||
transmitter site (source location), and plots the
|
||||
@@ -514,10 +674,7 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
|
||||
of a topographic map when the WritePPM() function
|
||||
is later invoked. */
|
||||
|
||||
int x, y, z;
|
||||
struct site edge;
|
||||
double lat, lon, minwest, maxnorth, th;
|
||||
static unsigned char mask_value = 1;
|
||||
static __thread unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
if (plo_filename[0] != 0)
|
||||
@@ -529,64 +686,44 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
th = ppd / loops;
|
||||
// Four sections start here
|
||||
// Process north edge east/west, east edge north/south,
|
||||
// south edge east/west, west edge north/south
|
||||
int range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||
int range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||
int range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||
int range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||
propagationRange* r[NUM_SECTIONS];
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||
propagationRange *range = new propagationRange;
|
||||
r[i] = range;
|
||||
range->los = true;
|
||||
|
||||
minwest = dpp + (double)min_west;
|
||||
maxnorth = (double)max_north - dpp;
|
||||
range->eastwest = (range_min_west[i] == range_max_west[i] ? false : true);
|
||||
range->min_west = range_min_west[i];
|
||||
range->max_west = range_max_west[i];
|
||||
range->min_north = range_min_north[i];
|
||||
range->max_north = range_max_north[i];
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
range->use_threads = use_threads;
|
||||
range->altitude = altitude;
|
||||
range->source = source;
|
||||
range->mask_value = mask_value;
|
||||
range->fd = fd;
|
||||
|
||||
edge.lat = max_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = maxnorth, x = 0, y = 0; lat >= (double)min_north;
|
||||
y++, lat = maxnorth - (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = min_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
if(use_threads)
|
||||
beginThread(range);
|
||||
else
|
||||
rangePropagation(range);
|
||||
|
||||
}
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = min_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = (double)min_north, x = 0, y = 0; lat < (double)max_north;
|
||||
y++, lat = (double)min_north + (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = max_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
if(use_threads)
|
||||
finishThreads();
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||
delete r[i];
|
||||
}
|
||||
|
||||
switch (mask_value) {
|
||||
@@ -603,21 +740,14 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
int propmodel, int knifeedge, int haf, int pmenv)
|
||||
int propmodel, int knifeedge, int haf, int pmenv, bool
|
||||
use_threads)
|
||||
{
|
||||
int y, z, count;
|
||||
struct site edge;
|
||||
double lat, lon, minwest, maxnorth, th;
|
||||
unsigned char x;
|
||||
static unsigned char mask_value = 1;
|
||||
static __thread unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
minwest = dpp + (double)min_west;
|
||||
maxnorth = (double)max_north - dpp;
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
if (LR.erp == 0.0 && debug)
|
||||
fprintf(stdout, "path loss");
|
||||
else {
|
||||
@@ -657,139 +787,57 @@ void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
th = ppd / loops;
|
||||
|
||||
// Four sections start here
|
||||
// Process north edge east/west, east edge north/south,
|
||||
// south edge east/west, west edge north/south
|
||||
int range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||
int range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||
int range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||
int range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||
propagationRange* r[NUM_SECTIONS];
|
||||
|
||||
//S1
|
||||
if (haf == 0 || haf == 1) {
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||
propagationRange *range = new propagationRange;
|
||||
r[i] = range;
|
||||
range->los = false;
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
// Only process correct half
|
||||
if((NUM_SECTIONS - i) <= (NUM_SECTIONS / 2) && haf == 1)
|
||||
continue;
|
||||
if((NUM_SECTIONS - i) > (NUM_SECTIONS / 2) && haf == 2)
|
||||
continue;
|
||||
|
||||
edge.lat = max_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
range->eastwest = (range_min_west[i] == range_max_west[i] ? false : true);
|
||||
range->min_west = range_min_west[i];
|
||||
range->max_west = range_max_west[i];
|
||||
range->min_north = range_min_north[i];
|
||||
range->max_north = range_max_north[i];
|
||||
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
range->use_threads = use_threads;
|
||||
range->altitude = altitude;
|
||||
range->source = source;
|
||||
range->mask_value = mask_value;
|
||||
range->fd = fd;
|
||||
range->propmodel = propmodel;
|
||||
range->knifeedge = knifeedge;
|
||||
range->pmenv = pmenv;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
if(use_threads)
|
||||
beginThread(range);
|
||||
else
|
||||
rangePropagation(range);
|
||||
|
||||
}
|
||||
//S2
|
||||
if (haf == 0 || haf == 1) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n25%c to 50%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = maxnorth, x = 0, y = 0; lat >= (double)min_north;
|
||||
y++, lat = maxnorth - (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = min_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
if(use_threads)
|
||||
finishThreads();
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||
delete r[i];
|
||||
}
|
||||
//S3
|
||||
if (haf == 0 || haf == 2) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n50%c to 75%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = min_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//S4
|
||||
if (haf == 0 || haf == 2) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n75%c to 100%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = (double)min_north, x = 0, y = 0;
|
||||
lat < (double)max_north;
|
||||
y++, lat = (double)min_north + (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = max_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
|
||||
if (count == z) {
|
||||
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
} //S4
|
||||
|
||||
if (fd != NULL)
|
||||
if (fd != NULL)
|
||||
fclose(fd);
|
||||
|
||||
if (mask_value < 30)
|
||||
|
Reference in New Issue
Block a user