Added propagation models and knife edge diffraction :)
This commit is contained in:
Cloud-RF
2013-12-30 21:41:03 +00:00
parent bf6a259c83
commit cdabfd517a
6 changed files with 367 additions and 125 deletions

View File

@@ -1,4 +1,11 @@
Signal Server 1.3.6 changelog Signal Server 1.3.7 changelog
v1.3.7 - 30 Dec 2013
Added propagation model option (-pm)
Added HATA urban/suburban/open models (150-1500MHz)
Added COST231-Hata (urban) model (1500-2000MHz)
Added custom Knife Edge Diffraction option (-ked) to enhance new models
Removed unused variables
v1.3.6 - 12 Aug 2013 v1.3.6 - 12 Aug 2013
Added LOS model for up to 100GHz Added LOS model for up to 100GHz

View File

@@ -1,16 +1,14 @@
Signal-Server Signal-Server RF coverage calculator
============= ====================================
RF coverage calculator
/****************************************************************************\ /****************************************************************************\
* Signal Server 1.3.6: Server optimised SPLAT! by Alex Farrant * * Signal Server 1.3.7: Server optimised SPLAT! by Alex Farrant *
****************************************************************************** ******************************************************************************
* SPLAT! Project started in 1997 by John A. Magliacane, KD2BD * * SPLAT! Project started in 1997 by John A. Magliacane, KD2BD *
* * * *
****************************************************************************** ******************************************************************************
* Please consult the SPLAT! documentation for a complete list of * * Please consult the SPLAT! documentation for a complete list of *
* individuals who have contributed to this project. * * individuals who have contributed to this project. *
****************************************************************************** ******************************************************************************
* * * *
* This program is free software; you can redistribute it and/or modify it * * This program is free software; you can redistribute it and/or modify it *
@@ -24,7 +22,7 @@ RF coverage calculator
* for more details. * * for more details. *
* * * *
****************************************************************************** ******************************************************************************
* g++ -Wall -O3 -s -lm -fomit-frame-pointer itm.cpp main.cpp -o ss * * g++ -Wall -O3 -s -lm -fomit-frame-pointer itm.cpp cost.cpp hata.cpp main.cpp -o ss *
\****************************************************************************/ \****************************************************************************/
Usage: Signalserver (options) Usage: Signalserver (options)
@@ -51,4 +49,7 @@ RF coverage calculator
-R Radius (miles/kilometers) -R Radius (miles/kilometers)
-res Pixels per degree. 300/600/1200(default)/3600 (optional) -res Pixels per degree. 300/600/1200(default)/3600 (optional)
-t Terrain background -t Terrain background
-dbg Debug -pm Propagation model. 1: ITM (Default), 2: LOS, 3-5: Hata
-ked Knife edge diffraction (Default for ITM)
-wf Win32 SDF tile names ('=' not ':')
-dbg Debug mode

41
cost.cpp Normal file
View File

@@ -0,0 +1,41 @@
/*****************************************************************************
* COST231-HATA MODEL for Signal Server by Alex Farrant *
* 30 December 2013 *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License or any later *
* version. *
* *
* This program is distributed in the hope that it will useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* */
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
double CostHataLinkdB(float f,float h_B, float h_M, float d){
/*
COST HATA URBAN model
Frequency 1500 to 2000MHz
h_B = Base station height 30 to 200m
h_M = Mobile station height 1 to 10m
Distance 1-20km
*/
int C = 0; // 0dB for suburban
float lh_M = log10(11.75*h_M);
float C_H = 3.2*lh_M*lh_M-4.97;
float logf = log10(f);
double dbloss = 46.3 + (33.9 * logf) - (13.82 * log10(h_B)) - C_H + (44.9 - 6.55 * log10(h_B)) * log10(d) + C;
return dbloss;
}

109
hata.cpp Normal file
View File

@@ -0,0 +1,109 @@
/*****************************************************************************
* HATA MODEL for Signal Server by Alex Farrant *
* 30 December 2013 *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License or any later *
* version. *
* *
* This program is distributed in the hope that it will useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* */
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
#define PI 3.14159265
/* Acute Angle from Rx point to an obstacle of height (opp) and distance (adj) */
double incidenceAngle(double opp, double adj){
return atan2(opp,adj) * 180 / PI;
}
/*
Knife edge diffraction:
This custom function adds to the overall path loss based upon the obstacle
angle (from receive point) and the frequency. Loss increases with angle and frequency.
This is not a recognised formula like Huygens, rather it is a
compromise for increased speed which adds a realistic diffraction effect.
*/
double ked(double freq, double elev[], double rxh, double dkm){
double obh,obd,rxobaoi=0,d;
obh=0;
obd=0;
dkm=dkm*1000; // KM to metres
for(int n=2;n<(dkm/elev[1]);n++){
d = (n-2)*elev[1]; // no of points * delta = km
//Find dip(s)
if(elev[n] > 0 && elev[n]<(obh+10)){
// Angle from Rx point to obstacle
rxobaoi = incidenceAngle((obh-(elev[n]+rxh)),d-obd);
} else{
// Line of sight or higher
rxobaoi=0;
}
//note the highest point
if(elev[n]>obh){
obh=elev[n];
obd=d;
}
}
if(rxobaoi >= 0){
return (rxobaoi * 3) / (300/freq); // Exaggerate diffraction angle and divide by wavelength (m)
}else{
return 0;
}
}
double HataLinkdB(float f,float h_B, float h_M, float d, int mode){
/*
HATA URBAN model for cellular planning
Frequency (MHz) 150 to 1500MHz
Base station height 30-200m
Mobile station height 1-10m
Distance 1-20km
mode 1 = URBAN
mode 2 = SUBURBAN
mode 3 = OPEN
*/
float lh_M = log10(11.75*h_M);
float C_H = 3.2*lh_M*lh_M-4.97;
float logf = log10(f);
float L_u = 69.55 + 26.16*logf - 13.82*log10(h_B) - C_H + (44.9 - 6.55*log10(h_B))*log10(d);
if(!mode || mode==1){
return L_u; //URBAN
}
if(mode==2){ //SUBURBAN
float logf_28 = log10(f/28);
return L_u - 2*logf_28*logf_28 - 5.4;
}
if(mode==3){ //OPEN
return L_u - 4.78*logf*logf + 18.33*logf - 40.94;
}
return 0;
}

View File

@@ -1215,9 +1215,9 @@ void point_to_point(double elev[], double tht_m, double rht_m, double eps_dielec
prop.mdp=-1; prop.mdp=-1;
zc=qerfi(conf); zc=qerfi(conf);
zr=qerfi(rel); zr=qerfi(rel);
np=(long)elev[0]; np=(long)elev[0]; //number of points
dkm=(elev[1]*elev[0])/1000.0; dkm=(elev[1]*elev[0])/1000.0; // total distance in km. elev[1]=90(m) (default)
xkm=elev[1]/1000.0; xkm=elev[1]/1000.0; // distance between points in km
eno=eno_ns_surfref; eno=eno_ns_surfref;
enso=0.0; enso=0.0;
q=enso; q=enso;

306
main.cpp
View File

@@ -1,11 +1,11 @@
/****************************************************************************\ /****************************************************************************\
* Signal Server 1.3.6: Server optimised SPLAT! by Alex Farrant * * Signal Server 1.3.7: Server optimised SPLAT! by Alex Farrant *
****************************************************************************** ******************************************************************************
* SPLAT! Project started in 1997 by John A. Magliacane, KD2BD * * SPLAT! Project started in 1997 by John A. Magliacane, KD2BD *
* * * *
****************************************************************************** ******************************************************************************
* Please consult the SPLAT! documentation for a complete list of * * Please consult the SPLAT! documentation for a complete list of *
* individuals who have contributed to this project. * * individuals who have contributed to this project. *
****************************************************************************** ******************************************************************************
* * * *
* This program is free software; you can redistribute it and/or modify it * * This program is free software; you can redistribute it and/or modify it *
@@ -19,7 +19,7 @@
* for more details. * * for more details. *
* * * *
****************************************************************************** ******************************************************************************
* g++ -Wall -O3 -s -lm -fomit-frame-pointer itm.cpp main.cpp -o ss * * g++ -Wall -O3 -s -lm -fomit-frame-pointer itm.cpp cost.cpp hata.cpp main.cpp -o ss *
\****************************************************************************/ \****************************************************************************/
#include <stdio.h> #include <stdio.h>
@@ -30,9 +30,9 @@
#include <unistd.h> #include <unistd.h>
#define GAMMA 2.5 #define GAMMA 2.5
#define MAXPAGES 9 #define MAXPAGES 64
#define ARRAYSIZE 32600 #define ARRAYSIZE 76810
#define IPPD 3600 #define IPPD 1200
#ifndef PI #ifndef PI
#define PI 3.141592653589793 #define PI 3.141592653589793
@@ -117,6 +117,12 @@ void point_to_point(double elev[], double tht_m, double rht_m,
double eps_dielect, double sgm_conductivity, double eno_ns_surfref, double eps_dielect, double sgm_conductivity, double eno_ns_surfref,
double frq_mhz, int radio_climate, int pol, double conf, double frq_mhz, int radio_climate, int pol, double conf,
double rel, double &dbloss, char *strmode, int &errnum); double rel, double &dbloss, char *strmode, int &errnum);
double HataLinkdB(float f,float h_B, float h_M, float d, int mode);
double CostHataLinkdB(float f,float h_B, float h_M, float d);
double ked(double freq, double elev[], double rxh, double dkm);
double arccos(double x, double y) double arccos(double x, double y)
{ {
@@ -1222,7 +1228,7 @@ void LoadPAT(char *filename)
} }
} }
int LoadSDF_SDF(char *name) int LoadSDF_SDF(char *name, int winfiles)
{ {
/* This function reads uncompressed ss Data Files (.sdf) /* This function reads uncompressed ss Data Files (.sdf)
containing digital elevation model data into memory. containing digital elevation model data into memory.
@@ -1243,9 +1249,12 @@ int LoadSDF_SDF(char *name)
sdf_file[x]=0; sdf_file[x]=0;
/* Parse filename for minimum latitude and longitude values */ /* Parse filename for minimum latitude and longitude values */
if(winfiles==1){
sscanf(sdf_file,"%d=%d=%d=%d",&minlat,&maxlat,&minlon,&maxlon);
}else{
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]='.'; sdf_file[x]='.';
sdf_file[x+1]='s'; sdf_file[x+1]='s';
sdf_file[x+2]='d'; sdf_file[x+2]='d';
@@ -1431,7 +1440,7 @@ int LoadSDF_SDF(char *name)
else else
return 0; return 0;
} }
char LoadSDF(char *name) char LoadSDF(char *name, int winfiles)
{ {
/* This function loads the requested SDF file from the filesystem. /* This function loads the requested SDF file from the filesystem.
It first tries to invoke the LoadSDF_SDF() function to load an It first tries to invoke the LoadSDF_SDF() function to load an
@@ -1446,7 +1455,7 @@ char LoadSDF(char *name)
char found, free_page=0; char found, free_page=0;
int return_value=-1; int return_value=-1;
return_value=LoadSDF_SDF(name); return_value=LoadSDF_SDF(name, winfiles);
/* If neither format can be found, then assume the area is water. */ /* If neither format can be found, then assume the area is water. */
@@ -1456,10 +1465,11 @@ char LoadSDF(char *name)
/* Parse SDF name for minimum latitude and longitude values */ if(winfiles==1){
sscanf(name,"%d=%d=%d=%d",&minlat,&maxlat,&minlon,&maxlon);
}else{
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? */ /* Is it already in memory? */
for (indx=0, found=0; indx<MAXPAGES && found==0; indx++) for (indx=0, found=0; indx<MAXPAGES && found==0; indx++)
@@ -1565,7 +1575,7 @@ char LoadSDF(char *name)
return return_value; return return_value;
} }
void PlotPath(struct site source, struct site destination, char mask_value, FILE *fd) void PlotLOSPath(struct site source, struct site destination, char mask_value, FILE *fd)
{ {
/* This function analyzes the path between the source and /* This function analyzes the path between the source and
destination locations. It determines which points along destination locations. It determines which points along
@@ -1623,36 +1633,37 @@ void PlotPath(struct site source, struct site destination, char mask_value, FILE
} }
} }
void PlotLRPath(struct site source, struct site destination, unsigned char mask_value, FILE *fd) void PlotPropPath(struct site source, struct site destination, unsigned char mask_value, FILE *fd, int propmodel, int knifeedge)
{ {
/* This function plots the RF path loss between source and
destination points based on the Longley-Rice propagation
model, taking into account antenna pattern data, if available. */
int x, y, ifs, ofs, errnum; int x, y, ifs, ofs, errnum;
char block=0, strmode[100]; char block=0, strmode[100];
double loss, azimuth, pattern=0.0, double loss, azimuth, pattern=0.0,
xmtr_alt, dest_alt, xmtr_alt2, dest_alt2, xmtr_alt, dest_alt, xmtr_alt2, dest_alt2,
cos_rcvr_angle, cos_test_angle=0.0, test_alt, cos_rcvr_angle, cos_test_angle=0.0, test_alt,
elevation=0.0, distance=0.0, four_thirds_earth, elevation=0.0, distance=0.0, radius=0.0, four_thirds_earth,
field_strength=0.0, rxp, dBm; field_strength=0.0, rxp, dBm, txelev, dkm, diffloss, lastdiffloss;
struct site temp; struct site temp;
radius = Distance(source,destination);
ReadPath(source,destination); ReadPath(source,destination);
four_thirds_earth=FOUR_THIRDS*EARTHRADIUS; four_thirds_earth=FOUR_THIRDS*EARTHRADIUS;
/* Copy elevations plus clutter along path into the elev[] array. */ /* Copy elevations plus clutter along path into the elev[] array. */
lastdiffloss=1;
for (x=1; x<path.length-1; x++) for (x=1; x<path.length-1; x++)
elev[x+2]=(path.elevation[x]==0.0?path.elevation[x]*METERS_PER_FOOT:(clutter+path.elevation[x])*METERS_PER_FOOT); elev[x+2]=(path.elevation[x]==0.0?path.elevation[x]*METERS_PER_FOOT:(clutter+path.elevation[x])*METERS_PER_FOOT);
/* Copy ending points without clutter */ /* Copy ending points without clutter */
elev[2]=path.elevation[0]*METERS_PER_FOOT; elev[2]=path.elevation[0]*METERS_PER_FOOT;
txelev=elev[2]+(source.alt*METERS_PER_FOOT);
elev[path.length+1]=path.elevation[path.length-1]*METERS_PER_FOOT; elev[path.length+1]=path.elevation[path.length-1]*METERS_PER_FOOT;
/* Since the only energy the Longley-Rice model considers /* Since the only energy the Longley-Rice model considers
reaching the destination is based on what is scattered reaching the destination is based on what is scattered
or deflected from the first obstruction along the path, or deflected from the first obstruction along the path,
@@ -1731,8 +1742,7 @@ void PlotLRPath(struct site source, struct site destination, unsigned char mask_
} }
/* Determine attenuation for each point along the /* Determine attenuation for each point along the
path using Longley-Rice's point_to_point mode path using a prop model starting at y=2 (number_of_points = 1), the
starting at y=2 (number_of_points = 1), the
shortest distance terrain can play a role in shortest distance terrain can play a role in
path loss. */ path loss. */
@@ -1742,12 +1752,66 @@ void PlotLRPath(struct site source, struct site destination, unsigned char mask_
elev[1]=METERS_PER_MILE*(path.distance[y]-path.distance[y-1]); elev[1]=METERS_PER_MILE*(path.distance[y]-path.distance[y-1]);
point_to_point(elev,source.alt*METERS_PER_FOOT, /*
destination.alt*METERS_PER_FOOT, LR.eps_dielect, elev[2]=path.elevation[0]*METERS_PER_FOOT;
LR.sgm_conductivity, LR.eno_ns_surfref, LR.frq_mhz, elev[path.length+1]=path.elevation[path.length-1]*METERS_PER_FOOT;
LR.radio_climate, LR.pol, LR.conf, LR.rel, loss, */
strmode, errnum); if(path.elevation[y] < 1){
path.elevation[y]=1;
}
dkm=(elev[1]*elev[0])/1000; // km
switch (propmodel)
{
case 1:
// Longley Rice
point_to_point(elev,source.alt*METERS_PER_FOOT,
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, errnum);
break;
case 3:
//HATA urban
loss=HataLinkdB(LR.frq_mhz,txelev,path.elevation[y]+(destination.alt*METERS_PER_FOOT),dkm, 1);
break;
case 4:
//HATA suburban
loss=HataLinkdB(LR.frq_mhz,txelev,path.elevation[y]+(destination.alt*METERS_PER_FOOT),dkm, 2);
break;
case 5:
//HATA open
loss=HataLinkdB(LR.frq_mhz,txelev,path.elevation[y]+(destination.alt*METERS_PER_FOOT),dkm, 3);
break;
case 6:
// COST231-HATA
loss=CostHataLinkdB(LR.frq_mhz,txelev,path.elevation[y]+(destination.alt*METERS_PER_FOOT),dkm);
break;
default:
point_to_point(elev,source.alt*METERS_PER_FOOT,
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, errnum);
}
if(knifeedge==1){
diffloss = ked(LR.frq_mhz,elev,destination.alt*METERS_PER_FOOT,dkm);
loss+=(diffloss); // ;)
}
if(debug){
fprintf(stdout,"\n%2f\t%2f\t%2f\t%2f",txelev,path.elevation[y],dkm,loss);
fflush(stdout);
}
//Key stage. Link dB for p2p is returned as 'loss'.
temp.lat=path.lat[y]; temp.lat=path.lat[y];
temp.lon=path.lon[y]; temp.lon=path.lon[y];
@@ -1877,9 +1941,9 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
of a topographic map when the WritePPM() function of a topographic map when the WritePPM() function
is later invoked. */ is later invoked. */
int y, z, count; int y, z;
struct site edge; struct site edge;
unsigned char symbol[4], x; unsigned char x;
double lat, lon, minwest, maxnorth, th; double lat, lon, minwest, maxnorth, th;
static unsigned char mask_value=1; static unsigned char mask_value=1;
FILE *fd=NULL; FILE *fd=NULL;
@@ -1909,7 +1973,7 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
edge.lon=lon; edge.lon=lon;
edge.alt=altitude; edge.alt=altitude;
PlotPath(source,edge,mask_value,fd); PlotLOSPath(source,edge,mask_value,fd);
} }
@@ -1922,7 +1986,7 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
edge.lon=min_west; edge.lon=min_west;
edge.alt=altitude; edge.alt=altitude;
PlotPath(source,edge,mask_value,fd); PlotLOSPath(source,edge,mask_value,fd);
} }
@@ -1939,7 +2003,7 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
edge.lon=lon; edge.lon=lon;
edge.alt=altitude; edge.alt=altitude;
PlotPath(source,edge,mask_value,fd); PlotLOSPath(source,edge,mask_value,fd);
} }
@@ -1952,7 +2016,7 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
edge.lon=max_west; edge.lon=max_west;
edge.alt=altitude; edge.alt=altitude;
PlotPath(source,edge,mask_value,fd); PlotLOSPath(source,edge,mask_value,fd);
} }
@@ -1973,21 +2037,12 @@ void PlotLOSMap(struct site source, double altitude, char *plo_filename)
} }
} }
void PlotLRMap(struct site source, double altitude, char *plo_filename) void PlotPropagation(struct site source, double altitude, char *plo_filename, int propmodel, int knifeedge)
{ {
/* This function performs a 360 degree sweep around the
transmitter site (source location), and plots the
Longley-Rice attenuation on the ss generated
topographic map based on a receiver located at
the specified altitude (in feet AGL). Results
are stored in memory, and written out in the form
of a topographic map when the DoPathLoss() or
DoSigStr() functions are later invoked. */
int y, z, count; int y, z, count;
struct site edge; struct site edge;
double lat, lon, minwest, maxnorth, th; double lat, lon, minwest, maxnorth, th;
unsigned char x, symbol[4]; unsigned char x;
static unsigned char mask_value=1; static unsigned char mask_value=1;
FILE *fd=NULL; FILE *fd=NULL;
@@ -1995,9 +2050,7 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
maxnorth=(double)max_north-dpp; maxnorth=(double)max_north-dpp;
count=0; count=0;
if (debug){
fprintf(stdout,"\nComputing Longley-Rice ");
}
if (LR.erp==0.0 && debug) if (LR.erp==0.0 && debug)
fprintf(stdout,"path loss"); fprintf(stdout,"path loss");
@@ -2025,14 +2078,9 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
if (fd!=NULL) if (fd!=NULL)
{ {
/* Write header information to output file */
fprintf(fd,"%d, %d\t; max_west, min_west\n%d, %d\t; max_north, min_north\n",max_west, min_west, max_north, min_north); fprintf(fd,"%d, %d\t; max_west, min_west\n%d, %d\t; max_north, min_north\n",max_west, min_west, max_north, min_north);
} }
/* th=pixels/degree divided by 64 loops per
progress indicator symbol (.oOo) printed. */
th=ppd/loops; th=ppd/loops;
z=(int)(th*ReduceAngle(max_west-min_west)); z=(int)(th*ReduceAngle(max_west-min_west));
@@ -2046,13 +2094,11 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
edge.lon=lon; edge.lon=lon;
edge.alt=altitude; edge.alt=altitude;
PlotLRPath(source,edge,mask_value,fd); PlotPropPath(source,edge,mask_value,fd,propmodel,knifeedge);
count++; count++;
if (count==z) if (count==z)
{ {
//fprintf(stdout,"%c",symbol[x]);
//fflush(stdout);
count=0; count=0;
if (x==3) if (x==3)
@@ -2075,7 +2121,7 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
edge.lon=min_west; edge.lon=min_west;
edge.alt=altitude; edge.alt=altitude;
PlotLRPath(source,edge,mask_value,fd); PlotPropPath(source,edge,mask_value,fd,propmodel,knifeedge);
count++; count++;
if (count==z) if (count==z)
@@ -2107,7 +2153,7 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
edge.lon=lon; edge.lon=lon;
edge.alt=altitude; edge.alt=altitude;
PlotLRPath(source,edge,mask_value,fd); PlotPropPath(source,edge,mask_value,fd,propmodel,knifeedge);
count++; count++;
if (count==z) if (count==z)
{ {
@@ -2136,13 +2182,12 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
edge.lon=max_west; edge.lon=max_west;
edge.alt=altitude; edge.alt=altitude;
PlotLRPath(source,edge,mask_value,fd); PlotPropPath(source,edge,mask_value,fd,propmodel,knifeedge);
count++; count++;
if (count==z) if (count==z)
{ {
//fprintf(stdout,"%c",symbol[x]);
//fflush(stdout);
count=0; count=0;
if (x==3) if (x==3)
@@ -3273,9 +3318,9 @@ void DoLOS(char *filename, unsigned char geo, unsigned char kml, unsigned char n
points up and east points right in the image generated. */ points up and east points right in the image generated. */
char mapfile[255], geofile[255], kmlfile[255]; char mapfile[255], geofile[255], kmlfile[255];
unsigned width, height, terrain, red, green, blue; unsigned width, height, terrain;
unsigned char found, mask, cityorcounty; unsigned char found, mask;
int indx, x, y, z=1, x0, y0, dBm, match; int indx, x, y, x0, y0;
double conversion, one_over_gamma, lat, lon, minwest; double conversion, one_over_gamma, lat, lon, minwest;
FILE *fd; FILE *fd;
@@ -3488,7 +3533,7 @@ void DoLOS(char *filename, unsigned char geo, unsigned char kml, unsigned char n
} }
void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat) void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat, int winfiles)
{ {
/* This function loads the SDF files required /* This function loads the SDF files required
to cover the limits of the region specified. */ to cover the limits of the region specified. */
@@ -3518,13 +3563,20 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat)
while (ymax>=360) while (ymax>=360)
ymax-=360; ymax-=360;
if (ippd==3600) if (winfiles==1){
snprintf(string,19,"%d:%d:%d:%d-hd",x, x+1, ymin, ymax); if (ippd==3600)
else snprintf(string,19,"%d=%d=%d=%d=hd",x, x+1, ymin, ymax);
snprintf(string,16,"%d:%d:%d:%d",x, x+1, ymin, ymax); else
snprintf(string,16,"%d=%d=%d=%d",x, x+1, ymin, ymax);
LoadSDF(string); }else{
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,winfiles);
} }
} }
@@ -3549,11 +3601,20 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat)
while (ymax>=360) while (ymax>=360)
ymax-=360; ymax-=360;
if (ippd==3600) if (winfiles==1){
snprintf(string,19,"%d:%d:%d:%d-hd",x, x+1, ymin, ymax); if (ippd==3600)
else snprintf(string,19,"%d=%d=%d=%d=hd",x, x+1, ymin, ymax);
snprintf(string,16,"%d:%d:%d:%d",x, x+1, ymin, ymax); else
LoadSDF(string); snprintf(string,16,"%d=%d=%d=%d",x, x+1, ymin, ymax);
}else{
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,winfiles);
} }
} }
} }
@@ -3725,7 +3786,7 @@ int main(int argc, char *argv[])
{ {
int x, y, z=0, min_lat, min_lon, max_lat, max_lon, int x, y, z=0, min_lat, min_lon, max_lat, max_lon,
rxlat, rxlon, txlat, txlon, west_min, west_max, rxlat, rxlon, txlat, txlon, west_min, west_max,
north_min, north_max; north_min, north_max, propmodel, winfiles,knifeedge=0;
unsigned char LRmap=0, map=0,txsites=0, unsigned char LRmap=0, map=0,txsites=0,
topomap=0, geo=0, kml=0, area_mode=0, max_txsites, ngs=0; topomap=0, geo=0, kml=0, area_mode=0, max_txsites, ngs=0;
@@ -3742,7 +3803,7 @@ int main(int argc, char *argv[])
strncpy(ss_version,"1.3.6\0",6); strncpy(ss_version,"1.3.7\0",6);
strncpy(ss_name,"Signal Server\0",14); strncpy(ss_name,"Signal Server\0",14);
if (argc==1) if (argc==1)
@@ -3769,7 +3830,10 @@ int main(int argc, char *argv[])
fprintf(stdout," -R Radius (miles/kilometers)\n"); fprintf(stdout," -R Radius (miles/kilometers)\n");
fprintf(stdout," -res Pixels per degree. 300/600/1200(default)/3600 (optional)\n"); fprintf(stdout," -res Pixels per degree. 300/600/1200(default)/3600 (optional)\n");
fprintf(stdout," -t Terrain background\n"); fprintf(stdout," -t Terrain background\n");
fprintf(stdout," -dbg Debug\n\n"); fprintf(stdout," -pm Propagation model. 1: ITM (Default), 2: LOS, 3-5: Hata\n");
fprintf(stdout," -ked Knife edge diffraction (Default for ITM)\n");
fprintf(stdout," -wf Win32 SDF tile names ('=' not ':')\n");
fprintf(stdout," -dbg Debug mode\n\n");
@@ -3806,8 +3870,9 @@ int main(int argc, char *argv[])
ano_filename[0]=0; ano_filename[0]=0;
ani_filename[0]=0; ani_filename[0]=0;
earthradius=EARTHRADIUS; earthradius=EARTHRADIUS;
max_range=1.0; max_range=1.0;
propmodel=1; //ITM
winfiles=0;
lat=0; lat=0;
lon=0; lon=0;
@@ -3822,8 +3887,8 @@ int main(int argc, char *argv[])
sscanf("0.1","%lf",&altitudeLR); sscanf("0.1","%lf",&altitudeLR);
// Defaults // Defaults
LR.eps_dielect=15.0; // Farmland LR.eps_dielect=15.0; // Farmland
LR.sgm_conductivity=0.005; // Farmland LR.sgm_conductivity=0.005; // Farmland
LR.eno_ns_surfref=301.0; LR.eno_ns_surfref=301.0;
LR.frq_mhz=19.0; // Deliberately too low LR.frq_mhz=19.0; // Deliberately too low
@@ -3837,10 +3902,6 @@ int main(int argc, char *argv[])
tx_site[0].lon=361.0; tx_site[0].lon=361.0;
//flush dem
//memset(dem, 0, ARRAYSIZE * sizeof(struct dem));
memset(dem, 0, (size_t)MAXPAGES * sizeof(struct dem));
for (x=0; x<MAXPAGES; x++) for (x=0; x<MAXPAGES; x++)
{ {
dem[x].min_el=32768; dem[x].min_el=32768;
@@ -3877,9 +3938,9 @@ int main(int argc, char *argv[])
jgets=1; jgets=1;
break; break;
case 3600: case 3600:
MAXRAD=100; MAXRAD=100;
ippd=3600; ippd=3600;
jgets=0; jgets=0;
break; break;
@@ -4146,9 +4207,9 @@ int main(int argc, char *argv[])
/*UDT*/ /*UDT*/
if (strcmp(argv[x],"-udt")==0) if (strcmp(argv[x],"-udt")==0)
{ {
z=x+1; z=x+1;
@@ -4158,7 +4219,31 @@ int main(int argc, char *argv[])
} }
} }
/*Prop model*/
if (strcmp(argv[x],"-pm")==0)
{
z=x+1;
if (z<=y && argv[z][0])
{
sscanf(argv[z],"%d",&propmodel);
}
}
//Knife edge diffraction
if (strcmp(argv[x],"-ked")==0)
{
z=x+1;
knifeedge=1;
}
//Windows friendly SDF filenames
if (strcmp(argv[x],"-wf")==0)
{
z=x+1;
winfiles=1;
}
} }
/* ERROR DETECTION */ /* ERROR DETECTION */
@@ -4221,7 +4306,10 @@ int main(int argc, char *argv[])
fprintf(stdout,"ERROR: Receiver threshold out of range (-200 / +200)"); fprintf(stdout,"ERROR: Receiver threshold out of range (-200 / +200)");
exit(0); exit(0);
} }
if(propmodel>2 && LR.frq_mhz < 150){
fprintf(stdout,"ERROR: Frequency too low for Propagation model");
exit(0);
}
/* ERROR DETECTION COMPLETE */ /* ERROR DETECTION COMPLETE */
@@ -4229,12 +4317,11 @@ int main(int argc, char *argv[])
if (metric) if (metric)
{ {
altitudeLR/=METERS_PER_FOOT; /* RXH meters --> feet */ altitudeLR/=METERS_PER_FOOT; /* 10ft * 0.3 = 3.3m */
max_range/=KM_PER_MILE; /* RAD kilometers --> miles */ max_range/=KM_PER_MILE; /* 10 / 1.6 = 7.5 */
altitude/=METERS_PER_FOOT; altitude/=METERS_PER_FOOT;
tx_site[0].alt/=METERS_PER_FOOT; /* TXH meters --> feet */ tx_site[0].alt/=METERS_PER_FOOT; /* Feet to metres */
clutter/=METERS_PER_FOOT; /* CLH meters --> feet */ clutter/=METERS_PER_FOOT; /* Feet to metres */
} }
/* Ensure a trailing '/' is present in sdf_path */ /* Ensure a trailing '/' is present in sdf_path */
@@ -4296,7 +4383,7 @@ int main(int argc, char *argv[])
/* Load the required SDF files */ /* Load the required SDF files */
LoadTopoData(max_lon, min_lon, max_lat, min_lat); LoadTopoData(max_lon, min_lon, max_lat, min_lat, winfiles);
if (area_mode || topomap) if (area_mode || topomap)
{ {
@@ -4381,22 +4468,19 @@ int main(int argc, char *argv[])
/* Load any additional SDF files, if required */ /* Load any additional SDF files, if required */
LoadTopoData(max_lon, min_lon, max_lat, min_lat); LoadTopoData(max_lon, min_lon, max_lat, min_lat, winfiles);
} }
// UDT clutter // UDT clutter
LoadUDT (udt_file); LoadUDT (udt_file);
if (LR.frq_mhz > 20000){ if (LR.frq_mhz > 20000 || propmodel==2){
PlotLOSMap(tx_site[0],altitudeLR,ano_filename); PlotLOSMap(tx_site[0],altitudeLR,ano_filename);
DoLOS(mapfile,geo,kml,ngs,tx_site,txsites); DoLOS(mapfile,geo,kml,ngs,tx_site,txsites);
} }
else{ else{
PlotLRMap(tx_site[0],altitudeLR,ano_filename); PlotPropagation(tx_site[0],altitudeLR,ano_filename,propmodel,knifeedge);
if (LR.erp==0.0) if (LR.erp==0.0)
DoPathLoss(mapfile,geo,kml,ngs,tx_site,txsites); DoPathLoss(mapfile,geo,kml,ngs,tx_site,txsites);