forked from ExternalVendorCode/Signal-Server
Initial Commit
This commit is contained in:
23
CHANGELOG
Normal file → Executable file
23
CHANGELOG
Normal file → Executable file
@@ -1,5 +1,28 @@
|
||||
SIGNAL SERVER CHANGELOG
|
||||
|
||||
3.20 Beta - 14 Jul 2019 - N9OZB Mods
|
||||
1. Added .GZ (Gzip) file processing for .sdf.gz DEM tiles.
|
||||
2. Added .BZ2 (Bzip2) file processing for .sdf.bz2 DEM tiles.
|
||||
3. Added much improved Antenna file options, new command line options for:
|
||||
a. AZ/EL file/path with a unique filename, no longer locked to output filename.
|
||||
b. Can specify command line pattern rotation azimuth, overrides value in file.
|
||||
c. Can specify command line pattern downtilt and direction, overrides file.
|
||||
4. Added command line option for color palette file, not locked to output name,
|
||||
filename/path is used for .scf, .lcf and .dcf files, depending on mode.
|
||||
5. Fixed major bug in .udt file processing in West (negative) longitudes.
|
||||
6. Fixed ITM "Conf" and "Rel" options (ITM "situations" and "times") on cmdline.
|
||||
7. Increased HD Version capacity from 9 to 32 DEM tiles (.sdf files).
|
||||
8. Updated command line help msg, CHANGELOG, and README.md documentation.
|
||||
9. Removed extra unused variables, cleaned up code and fixed a few logic issues.
|
||||
10. Restructured src tree, updated Makefile. Much cleaner directory structure.
|
||||
11. Added Antenna & UDT test file "ant-udt_test" to ./test.sh suite.
|
||||
12. Added sample color palette files in ./color.
|
||||
13. Added some conversion & postdownload scripts to ./utils/sdf.
|
||||
14. Added sample antenna file DB413-B in ./antenna.
|
||||
15. Tried to keep cmdline color/antenna and all changes backward compatible.
|
||||
16. Added base run (runsig.sh) and kmz conversion script (genkmz.sh) files.
|
||||
17. Added dandy User Manual for reference.
|
||||
|
||||
3.11 - 25 Sept 2018
|
||||
More LIDAR edge cases, tidying of many meridian hacks(!) and regression tested with different LIDAR resolutions and configurations eg. 1x2, 2x1..
|
||||
Meridian issue fixed for 30m but deliberately broken for 2m due to previous crap hacks causing a headache. Can be fixed in DEM by re-processing LIDAR tiles to NOT span the meridian.
|
||||
|
107
README.md
107
README.md
@@ -4,6 +4,7 @@ Multi-threaded radio propagation simulator based upon SPLAT! by Alex Farrant QCV
|
||||
SPLAT! Project started in 1997 by John A. Magliacane, KD2BD
|
||||
|
||||
This server application will generate RF coverage predictions, producing either 2D profile plots (Point-to-Point) or 360 degree polar plots in WGS-84 projection as PPM Bitmaps.
|
||||
|
||||
For detailed information and historical reference data related to this project see the SPLAT! documentation. Propagation models added to this project have been sourced from reputable academic sources and all efforts have been taken to ensure their accurate implementation. Not all models are ITU ratified and you use them entirely at your own risk.
|
||||
|
||||
WARNING: The accuracy of the output is directly proportional to the accuracy of the inputs and the time taken defining and validating them.
|
||||
@@ -18,11 +19,36 @@ WARNING: The accuracy of the output is directly proportional to the accuracy of
|
||||
|
||||
Signal Server is a very resource intensive multicore application. Only publish it for common use if you know what you are doing and you are advised to wrap it with another script to perform input validation.
|
||||
|
||||
Additional programs/scripts will be required to prepare inputs such as .sdf tiles (srtm2sdf.c), 3D antenna patterns (.ant) and user defined clutter (.udt) or manipulate the bitmap output (.ppm). More information can be found in the SPLAT! project.
|
||||
Additional programs/scripts will be required to prepare inputs such as .hgt tiles (srtm2sdf.c), 3D antenna patterns (.ant) and user defined clutter (.udt) or manipulate the bitmap output (.ppm). More information can be found in the SPLAT! project.
|
||||
|
||||
|
||||
## File extensions and types used by signalserver:
|
||||
.asc LIDAR topo data file in ASCII grid format.
|
||||
.jpg LIDAR topo data file in JPEG format.
|
||||
.sdf SPLAT! topo data file in SPLAT! format, lo-res 90m (from SRTM3).
|
||||
.sdf.gz topo data file in SPLAT! data format, gzip compressed, lo-res 90m.
|
||||
.sdf.bz2 topo data file in SPLAT! data format, bzip2 compressed, lo-res 90m.
|
||||
-hd.sdf SPLAT! topo data file in SPLAT! format, hi-res 30m (from SRTM1).
|
||||
-hd.sdf.gz topo data file in SPLAT! data format, gzip compressed, hi-res 30m.
|
||||
-hd.sdf.bz2 topo data file in SPLAT! data format, bzip2 compressed, lo-res 90m.
|
||||
.scf signal level color palette file.
|
||||
.lcf loss level color palette file.
|
||||
.dcf dbm level color palette file.
|
||||
.az SPLAT! antenna pattern azimuth data file.
|
||||
.el SPLAT! antenna pattern elevation data file.
|
||||
.lrp LIDAR antenna pattern data file.
|
||||
.udt user defined terrain data clutter data text file.
|
||||
.sh miscellaneous shell scripts and batch files.
|
||||
.ppm portable pixmap - output plot graphic rendering (native).
|
||||
.png portable network graphics - output plot graphic rendering (converted).
|
||||
.kml Google Earth Keyhole Markup Language - output viewable with Google Earth.
|
||||
.kmz Google Earth Keyhole Markup Language, compressed.
|
||||
|
||||
|
||||
## Installation
|
||||
```
|
||||
make
|
||||
cd src
|
||||
make install
|
||||
```
|
||||
|
||||
## Test
|
||||
@@ -32,48 +58,60 @@ make
|
||||
|
||||
## Parameters
|
||||
```
|
||||
Version: Signal Server 3.05 (Built for 100 DEM tiles at 1200 pixels)
|
||||
Version: Signal Server 3.20 (Built for 100 DEM tiles at 1200 pixels)
|
||||
License: GNU General Public License (GPL) version 2
|
||||
|
||||
Radio propagation simulator by Alex Farrant QCVS, 2E0TDW
|
||||
Based upon SPLAT! by John Magliacane, KD2BD
|
||||
Some feature enhancements/additions by Aaron A. Collins, N9OZB
|
||||
|
||||
Usage: signalserver [data options] [input options] [output options] -o outputfile
|
||||
Usage: signalserver [data options] [input options] [antenna options] [output options] -o outputfile
|
||||
|
||||
Data:
|
||||
-sdf Directory containing SRTM derived .sdf DEM tiles
|
||||
-sdf Directory containing SRTM derived .sdf DEM tiles (may be .gz or .bz2)
|
||||
-lid ASCII grid tile (LIDAR) with dimensions and resolution defined in header
|
||||
-udt User defined point clutter as decimal co-ordinates: 'latitude,longitude,height'
|
||||
-clt MODIS 17-class wide area clutter in ASCII grid format
|
||||
-color File to pre-load .scf/.lcf/.dcf for Signal/Loss/dBm color palette
|
||||
Input:
|
||||
-lat Tx Latitude (decimal degrees) -70/+70
|
||||
-lon Tx Longitude (decimal degrees) -180/+180
|
||||
-txh Tx Height (above ground)
|
||||
-rla (Optional) Rx Latitude for PPA (decimal degrees) -70/+70
|
||||
-rlo (Optional) Rx Longitude for PPA (decimal degrees) -180/+180
|
||||
-f Tx Frequency (MHz) 20MHz to 100GHz (LOS after 20GHz)
|
||||
-erp Tx Effective Radiated Power (Watts) including Tx+Rx gain
|
||||
-rxh Rx Height(s) (optional. Default=0.1)
|
||||
-rxg Rx gain dBi (optional for text report)
|
||||
-hp Horizontal Polarisation (default=vertical)
|
||||
-erp Tx Total Effective Radiated Power in Watts (dBd) inc Tx+Rx gain. 2.14dBi = 0dBd
|
||||
-gc Random ground clutter (feet/meters)
|
||||
-m Metric units of measurement
|
||||
-te Terrain code 1-6 (optional)
|
||||
-te Terrain code 1-6 (optional - 1. Water, 2. Marsh, 3. Farmland,
|
||||
4. Mountain, 5. Desert, 6. Urban
|
||||
-terdic Terrain dielectric value 2-80 (optional)
|
||||
-tercon Terrain conductivity 0.01-0.0001 (optional)
|
||||
-cl Climate code 1-6 (optional)
|
||||
-rel Reliability for ITM model 50 to 99 (optional)
|
||||
-resample Resample Lidar input to specified resolution in meters (optional)
|
||||
-cl Climate code 1-7 (optional - 1. Equatorial 2. Continental subtropical
|
||||
3. Maritime subtropical 4. Desert 5. Continental temperate
|
||||
6. Maritime temperate (Land) 7. Maritime temperate (Sea)
|
||||
-rel Reliability for ITM model (% of 'time') 1 to 99 (optional, default 50%)
|
||||
-conf Confidence for ITM model (% of 'situations') 1 to 99 (optional, default 50%)
|
||||
-resample Reduce Lidar resolution by specified factor (2 = 50%)
|
||||
Output:
|
||||
-dbm Plot Rxd signal power instead of field strength
|
||||
-o basename (Output file basename - required)
|
||||
-dbm Plot Rxd signal power instead of field strength in dBuV/m
|
||||
-rt Rx Threshold (dB / dBm / dBuV/m)
|
||||
-o Filename. Required.
|
||||
-R Radius (miles/kilometers)
|
||||
-res Pixels per tile. 300/600/1200/3600 (Optional. LIDAR res is within the tile)
|
||||
-pm Propagation model. 1: ITM, 2: LOS, 3: Hata, 4: ECC33,
|
||||
5: SUI, 6: COST-Hata, 7: FSPL, 8: ITWOM, 9: Ericsson, 10: Plane earth, 11: Egli VHF/UHF
|
||||
5: SUI, 6: COST-Hata, 7: FSPL, 8: ITWOM, 9: Ericsson,
|
||||
10: Plane earth, 11: Egli VHF/UHF, 12: Soil
|
||||
-pe Propagation model mode: 1=Urban,2=Suburban,3=Rural
|
||||
-ked Knife edge diffraction (Already on for ITM)
|
||||
Antenna:
|
||||
-ant (antenna pattern file basename+path for .az and .el files)
|
||||
-txh Tx Height (above ground)
|
||||
-rxh Rx Height(s) (optional. Default=0.1)
|
||||
-rxg Rx gain dBd (optional for PPA text report)
|
||||
-hp Horizontal Polarisation (default=vertical)
|
||||
-rot ( 0.0 - 359.0 degrees, default 0.0) Antenna Pattern Rotation
|
||||
-dt ( -10.0 - 90.0 degrees, default 0.0) Antenna Downtilt
|
||||
-dtdir ( 0.0 - 359.0 degrees, default 0.0) Antenna Downtilt Direction
|
||||
Debugging:
|
||||
-t Terrain greyscale background
|
||||
-dbg Verbose debug messages
|
||||
@@ -84,16 +122,20 @@ Debugging:
|
||||
|
||||
### REFERENCE DATA
|
||||
Signal server is designed for most of the environments and climates on Planet Earth but Polar region support is limited above extreme latitudes. (Svalbard is ok).
|
||||
It can run with or without terrain data and can even be used to simulate radiation of other EM emissions like light.
|
||||
|
||||
It can run with or without terrain data and can even be used to simulate radiation of other EM emissions like light.
|
||||
|
||||
#### -sdf
|
||||
##### Directory containing Digital Elevation Models (DEM)
|
||||
SDF formatted tiles can be created by converting SRTM tiles (30m or 90m) in HGT format with the [srtm2sdf.c](https://www.google.co.uk/search?q=srtm2sdf.c) utility from SPLAT!. At the time of writing these tiles can be obtained for free from the [USGS website](https://dds.cr.usgs.gov/srtm/).
|
||||
|
||||
Note these can be compressed using gzip or bzip2 if desired to save disk space and speed up loading the files. For hi-res (HD) SRTM1 (30m) data, bzip2 compresses best, and for lo-res SRTM3 (90m) data, gzip seems to achieve the best compression. Either will work fine for whichever data format and resolution is used.
|
||||
|
||||
|
||||
#### -lid
|
||||
##### WGS84 ASCII grid tile (LIDAR) with dimensions and resolution defined in header
|
||||
LIDAR data can be used providing it is in ASCII grid format with WGS84 projection. Resolutions up to 25cm have been tested. 2m is recommended for a good trade off. Cellsize should be in degrees and co-ordinates must be in WGS84 decimal degrees.
|
||||
|
||||
To load multiple tiles use commas eg. -lid tile1.asc,tile2.asc. You can load in different resolution tiles and use -resample to set the desired resolution (limited by data limit).
|
||||
```
|
||||
ncols 2454
|
||||
@@ -101,24 +143,27 @@ nrows 1467
|
||||
xllcorner -1.475333294357
|
||||
yllcorner 53.378635095801
|
||||
cellsize 0.000006170864
|
||||
NODATA_value 0
|
||||
NODATA_value 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 ...
|
||||
```
|
||||
|
||||
#### -udt
|
||||
##### User defined CSV clutter file
|
||||
This text file allows you to define buildings with co-ordinates and heights.
|
||||
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 in memory. Height units are determined by appending M for meters or nothing for feet.
|
||||
Format: latitude,longitude,height
|
||||
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 in memory. Height units are determined by appending M for meters or nothing for feet.
|
||||
|
||||
There is no special parsing for comments, so any lines of data that don't contain 3 numbers separated by commas are interpreted as a comment.
|
||||
|
||||
Format: latitude,longitude,height(M)
|
||||
```
|
||||
// This is a comment!
|
||||
54.555,-2.221,10M
|
||||
54.555,-2.222,10M
|
||||
54.555,-2.223,10M
|
||||
```
|
||||
|
||||
### Antenna radiation pattern(s)
|
||||
Antenna pattern data is read from a pair of files having the same base name as the output file (-o), but with .az and .el extensions for azimuth and elevation patterns.
|
||||
Antenna pattern data is read from a pair of files having the same base name as the output file (-o), but with .az and .el extensions for azimuth and elevation patterns. This name can be overridden with the command line option -ant followed by a base filename or path and base filename for the .az and .el files. The program will first search for command line specified antenna files with -ant, then it will default to searching for antenna files having the same name as the output file.
|
||||
```
|
||||
045.0
|
||||
0 0.8950590
|
||||
@@ -128,11 +173,11 @@ Format: latitude,longitude,height
|
||||
4 0.9009535
|
||||
5 0.9022749
|
||||
```
|
||||
The first line of the .az file specifies the direction measured clockwise in degrees from True North. This is followed by azimuth headings (0 to 360 degrees) and their associated normalized field patterns (0.000 to 1.000) separated by whitespace.
|
||||
The first line of the .az file specifies the direction measured clockwise in degrees from True North. This is followed by azimuth headings (0 to 360 degrees) and their associated normalized field patterns (0.000 to 1.000) separated by whitespace. This direction can be overridden by the command line option -rot followed by a positive direction value from 0 to 360 degrees. This value will override any direction specified in the first line of the .az file. If not specified on the command line, the program will default to using the direction from the first line of the .az file.
|
||||
|
||||
The structure of SPLAT! elevation pattern files is slightly different. The first line of the .el file specifies the amount of mechanical beamtilt applied to the antenna. A downward tilt is expressed as a positive angle, while an upward tilt is expressed as a negative angle. This data is followed by the azimuthal direction of the tilt, separated by whitespace.
|
||||
The remainder of the file consists of elevation angles and their radiation pattern (0.000 to 1.000) values separated by whitespace. Elevation angles must be specified over a -10.0 to +90.0 degree range. In this example, the antenna is tilted down 2
|
||||
degrees towards an azimuth of 045.0 degrees.
|
||||
The structure of SPLAT! elevation pattern files is slightly different. The first line of the .el file specifies the amount of mechanical beamtilt applied to the antenna. A downward tilt is expressed as a positive angle, while an upward tilt is expressed as a negative angle. This data is followed by the azimuthal direction of the tilt, 0 to 360 degrees, separated by whitespace. These can be overridden by the command line options -dt for downtilt and -dtdir for downtilt azimuthal direction. The options, like -rot above, will override any values embedded in the .el file if specified on the command line.
|
||||
|
||||
The remainder of the file consists of elevation angles and their radiation pattern (0.000 to 1.000) values separated by whitespace. Elevation angles must be specified over a -10.0 to +90.0 degree range. In this example, the antenna is tilted down 2 degrees towards an azimuth of 045.0 degrees.
|
||||
```
|
||||
2.0 045.0
|
||||
-10.0 0.172
|
||||
@@ -163,3 +208,11 @@ degrees towards an azimuth of 045.0 degrees.
|
||||
```
|
||||
./signalserverLIDAR -lid /data/LIDAR/Gloucester_2m.asc -lat 51.849 -lon -2.2299 -txh 15 -f 1800 -erp 1 -rxh 2 -rt -90 -dbm -m -o test3 -R 1 -pm 1
|
||||
```
|
||||
### Scripting
|
||||
By using wrapper scripts like runsig.sh and genkmz.sh, you can streamline running signalserver by pre-setting some commonly used options in the runsig.sh file. Those options should the be ones you use every time you run signalserver, like "-m" for metric or "-sdf ./sdf_file_path", for example, so you won't have to specify those options every time you run it. The genkmz.sh file will convert the output ppm file into a .png with transparent background, then will convert it to a Google Earth Keyhole Markup Language (KML) file, and then it compresses it for size to a (KMZ) file. For example, using the provided sample runsig.sh and genkmz.sh:
|
||||
|
||||
### Plot 70cm Service contour, 700W ERP, 300 feet AGL, DB413-B, to 150 mi:
|
||||
sudo ./runsig.sh -lat 42.428889 -lon -87.812500 -txh 300 -f 446.000 -erp 700 -R 150 -res 600 -rel 50 -rt 39 -ant antenna/DB413-B -rot 225 -color color/blue -o example-service | ./genkmz.sh
|
||||
|
||||
### Plot 70cm Interference contour, 700W ERP, 300 feet AGL, DB413-B, to 150 mi:
|
||||
sudo ./runsig.sh -lat 42.428889 -lon -87.812500 -txh 300 -f 446.000 -erp 700 -R 150 -res 600 -rel 10 -rt 21 -ant antenna/DB413-B -rot 225 -color color/blue -o example-service | ./genkmz.sh
|
||||
|
BIN
SignalServer_Manual.odt
Normal file
BIN
SignalServer_Manual.odt
Normal file
Binary file not shown.
720
antenna/DB413-B.ant
Normal file
720
antenna/DB413-B.ant
Normal file
@@ -0,0 +1,720 @@
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.3
|
||||
-0.3
|
||||
-0.3
|
||||
-0.3
|
||||
-0.4
|
||||
-0.4
|
||||
-0.4
|
||||
-0.5
|
||||
-0.5
|
||||
-0.5
|
||||
-0.6
|
||||
-0.6
|
||||
-0.6
|
||||
-0.7
|
||||
-0.7
|
||||
-0.8
|
||||
-0.8
|
||||
-0.8
|
||||
-0.9
|
||||
-0.9
|
||||
-1
|
||||
-1
|
||||
-1.1
|
||||
-1.1
|
||||
-1.2
|
||||
-1.2
|
||||
-1.3
|
||||
-1.4
|
||||
-1.4
|
||||
-1.5
|
||||
-1.5
|
||||
-1.6
|
||||
-1.6
|
||||
-1.7
|
||||
-1.8
|
||||
-1.9
|
||||
-1.9
|
||||
-2
|
||||
-2.1
|
||||
-2.1
|
||||
-2.2
|
||||
-2.3
|
||||
-2.4
|
||||
-2.5
|
||||
-2.5
|
||||
-2.6
|
||||
-2.7
|
||||
-2.8
|
||||
-2.9
|
||||
-3
|
||||
-3
|
||||
-3.1
|
||||
-3.2
|
||||
-3.3
|
||||
-3.4
|
||||
-3.5
|
||||
-3.6
|
||||
-3.7
|
||||
-3.8
|
||||
-3.9
|
||||
-4
|
||||
-4.1
|
||||
-4.3
|
||||
-4.4
|
||||
-4.5
|
||||
-4.6
|
||||
-4.7
|
||||
-4.8
|
||||
-4.9
|
||||
-5
|
||||
-5.2
|
||||
-5.3
|
||||
-5.4
|
||||
-5.5
|
||||
-5.6
|
||||
-5.8
|
||||
-5.9
|
||||
-6
|
||||
-6.1
|
||||
-6.2
|
||||
-6.4
|
||||
-6.5
|
||||
-6.6
|
||||
-6.7
|
||||
-6.8
|
||||
-7
|
||||
-7.1
|
||||
-7.2
|
||||
-7.3
|
||||
-7.4
|
||||
-7.6
|
||||
-7.7
|
||||
-7.8
|
||||
-7.9
|
||||
-8
|
||||
-8.1
|
||||
-8.2
|
||||
-8.3
|
||||
-8.4
|
||||
-8.5
|
||||
-8.6
|
||||
-8.7
|
||||
-8.8
|
||||
-8.9
|
||||
-8.9
|
||||
-9
|
||||
-9.1
|
||||
-9.2
|
||||
-9.2
|
||||
-9.3
|
||||
-9.3
|
||||
-9.4
|
||||
-9.4
|
||||
-9.5
|
||||
-9.5
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.8
|
||||
-9.8
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.5
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.8
|
||||
-9.8
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.7
|
||||
-9.6
|
||||
-9.6
|
||||
-9.6
|
||||
-9.5
|
||||
-9.5
|
||||
-9.4
|
||||
-9.4
|
||||
-9.3
|
||||
-9.3
|
||||
-9.2
|
||||
-9.2
|
||||
-9.1
|
||||
-9
|
||||
-8.9
|
||||
-8.9
|
||||
-8.8
|
||||
-8.7
|
||||
-8.6
|
||||
-8.5
|
||||
-8.4
|
||||
-8.3
|
||||
-8.2
|
||||
-8.1
|
||||
-8
|
||||
-7.9
|
||||
-7.8
|
||||
-7.7
|
||||
-7.6
|
||||
-7.4
|
||||
-7.3
|
||||
-7.2
|
||||
-7.1
|
||||
-7
|
||||
-6.8
|
||||
-6.7
|
||||
-6.6
|
||||
-6.5
|
||||
-6.4
|
||||
-6.2
|
||||
-6.1
|
||||
-6
|
||||
-5.9
|
||||
-5.8
|
||||
-5.6
|
||||
-5.5
|
||||
-5.4
|
||||
-5.3
|
||||
-5.2
|
||||
-5
|
||||
-4.9
|
||||
-4.8
|
||||
-4.7
|
||||
-4.6
|
||||
-4.5
|
||||
-4.4
|
||||
-4.3
|
||||
-4.1
|
||||
-4
|
||||
-3.9
|
||||
-3.8
|
||||
-3.7
|
||||
-3.6
|
||||
-3.5
|
||||
-3.4
|
||||
-3.3
|
||||
-3.2
|
||||
-3.1
|
||||
-3
|
||||
-3
|
||||
-2.9
|
||||
-2.8
|
||||
-2.7
|
||||
-2.6
|
||||
-2.5
|
||||
-2.5
|
||||
-2.4
|
||||
-2.3
|
||||
-2.2
|
||||
-2.1
|
||||
-2.1
|
||||
-2
|
||||
-1.9
|
||||
-1.9
|
||||
-1.8
|
||||
-1.7
|
||||
-1.6
|
||||
-1.6
|
||||
-1.5
|
||||
-1.5
|
||||
-1.4
|
||||
-1.4
|
||||
-1.3
|
||||
-1.2
|
||||
-1.2
|
||||
-1.1
|
||||
-1.1
|
||||
-1
|
||||
-1
|
||||
-0.9
|
||||
-0.9
|
||||
-0.8
|
||||
-0.8
|
||||
-0.8
|
||||
-0.7
|
||||
-0.7
|
||||
-0.6
|
||||
-0.6
|
||||
-0.6
|
||||
-0.5
|
||||
-0.5
|
||||
-0.5
|
||||
-0.4
|
||||
-0.4
|
||||
-0.4
|
||||
-0.3
|
||||
-0.3
|
||||
-0.3
|
||||
-0.3
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.2
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
-0.1
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
-40
|
||||
-32.8
|
||||
-26.7
|
||||
-23.1
|
||||
-20.6
|
||||
-18.6
|
||||
-17
|
||||
-15.6
|
||||
-14.4
|
||||
-13.4
|
||||
-12.5
|
||||
-11.7
|
||||
-11
|
||||
-10.5
|
||||
-10
|
||||
-9.6
|
||||
-9.3
|
||||
-9.1
|
||||
-9.1
|
||||
-9.1
|
||||
-9.4
|
||||
-9.7
|
||||
-10.3
|
||||
-11.2
|
||||
-12.3
|
||||
-13.8
|
||||
-15.8
|
||||
-18.4
|
||||
-21.8
|
||||
-23.9
|
||||
-21.9
|
||||
-19
|
||||
-16.8
|
||||
-15.3
|
||||
-14.5
|
||||
-14.2
|
||||
-14.4
|
||||
-15.2
|
||||
-16.7
|
||||
-19.2
|
||||
-23
|
||||
-27.9
|
||||
-26.5
|
||||
-22.2
|
||||
-19.5
|
||||
-18.2
|
||||
-17.8
|
||||
-18.3
|
||||
-19.8
|
||||
-22.5
|
||||
-26.7
|
||||
-28.3
|
||||
-24.4
|
||||
-21.3
|
||||
-19.7
|
||||
-19.2
|
||||
-19.7
|
||||
-21.3
|
||||
-24.2
|
||||
-27.9
|
||||
-27.1
|
||||
-23.4
|
||||
-21
|
||||
-19.8
|
||||
-19.8
|
||||
-20.9
|
||||
-23.4
|
||||
-27.4
|
||||
-27.8
|
||||
-23.2
|
||||
-20.1
|
||||
-18.4
|
||||
-18.1
|
||||
-19.1
|
||||
-22.2
|
||||
-28.2
|
||||
-24.9
|
||||
-18.8
|
||||
-15.5
|
||||
-14
|
||||
-14
|
||||
-15.9
|
||||
-22
|
||||
-23.5
|
||||
-13.2
|
||||
-8
|
||||
-4.7
|
||||
-2.5
|
||||
-1
|
||||
-0.2
|
||||
0
|
||||
-0.3
|
||||
-1.3
|
||||
-2.9
|
||||
-5.4
|
||||
-9.3
|
||||
-16
|
||||
-40
|
||||
-18.5
|
||||
-14.4
|
||||
-13.3
|
||||
-13.9
|
||||
-16.1
|
||||
-20.2
|
||||
-26.7
|
||||
-25.3
|
||||
-21
|
||||
-19.1
|
||||
-18.9
|
||||
-19.9
|
||||
-21.9
|
||||
-24.6
|
||||
-26.4
|
||||
-25.4
|
||||
-23.5
|
||||
-22.2
|
||||
-21.5
|
||||
-21.4
|
||||
-22.1
|
||||
-23.6
|
||||
-26.1
|
||||
-28.5
|
||||
-27.2
|
||||
-24.1
|
||||
-21.9
|
||||
-20.8
|
||||
-20.7
|
||||
-21.8
|
||||
-24.4
|
||||
-29.8
|
||||
-34.8
|
||||
-26.9
|
||||
-22.5
|
||||
-20.1
|
||||
-19
|
||||
-18.9
|
||||
-19.7
|
||||
-21.7
|
||||
-25.5
|
||||
-34.3
|
||||
-34.3
|
||||
-25.4
|
||||
-21.5
|
||||
-19.5
|
||||
-18.4
|
||||
-18.2
|
||||
-18.8
|
||||
-20.2
|
||||
-23
|
||||
-28.5
|
||||
-37.7
|
||||
-26.2
|
||||
-20.7
|
||||
-17.4
|
||||
-15
|
||||
-13.4
|
||||
-12.1
|
||||
-11.2
|
||||
-10.6
|
||||
-10.1
|
||||
-9.8
|
||||
-9.7
|
||||
-9.7
|
||||
-9.9
|
||||
-10.1
|
||||
-10.5
|
||||
-10.9
|
||||
-11.5
|
||||
-12.1
|
||||
-12.8
|
||||
-13.6
|
||||
-14.6
|
||||
-15.6
|
||||
-16.8
|
||||
-18.2
|
||||
-19.8
|
||||
-21.8
|
||||
-24.4
|
||||
-27.9
|
||||
-34
|
||||
-40
|
||||
-34
|
||||
-28
|
||||
-24.5
|
||||
-22
|
||||
-20
|
||||
-18.4
|
||||
-17.1
|
||||
-15.9
|
||||
-14.9
|
||||
-14
|
||||
-13.2
|
||||
-12.5
|
||||
-11.9
|
||||
-11.4
|
||||
-11
|
||||
-10.7
|
||||
-10.5
|
||||
-10.4
|
||||
-10.4
|
||||
-10.6
|
||||
-10.9
|
||||
-11.4
|
||||
-12.1
|
||||
-13.1
|
||||
-14.4
|
||||
-16.1
|
||||
-18.5
|
||||
-21.8
|
||||
-26.7
|
||||
-30.3
|
||||
-26
|
||||
-22.3
|
||||
-20
|
||||
-18.7
|
||||
-18.1
|
||||
-18.1
|
||||
-18.8
|
||||
-19.9
|
||||
-21.6
|
||||
-23.4
|
||||
-24.1
|
||||
-23.2
|
||||
-21.8
|
||||
-20.7
|
||||
-20.3
|
||||
-20.6
|
||||
-21.6
|
||||
-23.5
|
||||
-25.8
|
||||
-27
|
||||
-25.6
|
||||
-23.7
|
||||
-22.5
|
||||
-22.3
|
||||
-22.9
|
||||
-24.5
|
||||
-26.8
|
||||
-28.1
|
||||
-26.8
|
||||
-25
|
||||
-23.9
|
||||
-23.8
|
||||
-24.7
|
||||
-26.4
|
||||
-28.2
|
||||
-28.2
|
||||
-26.8
|
||||
-25.5
|
||||
-25.1
|
||||
-25.6
|
||||
-26.8
|
||||
-28.3
|
||||
-29.4
|
||||
-29.4
|
||||
-28.9
|
||||
-28.3
|
||||
-28.1
|
||||
-28.2
|
||||
-28.5
|
||||
-28.3
|
||||
-26
|
||||
-22.2
|
||||
-18.5
|
||||
-15.4
|
||||
-12.9
|
||||
-11
|
||||
-9.6
|
||||
-8.6
|
||||
-8.1
|
||||
-8
|
||||
-8.5
|
||||
-9.5
|
||||
-11.3
|
||||
-14.2
|
||||
-18.6
|
||||
-23.7
|
||||
-21.2
|
||||
-17.8
|
||||
-16.3
|
||||
-16.3
|
||||
-17.8
|
||||
-21.1
|
||||
-28.5
|
||||
-37.9
|
||||
-25.4
|
||||
-22
|
||||
-21.3
|
||||
-22.5
|
||||
-25.9
|
||||
-33.8
|
||||
-32.2
|
||||
-25.9
|
||||
-23.3
|
||||
-22.8
|
||||
-23.9
|
||||
-26.8
|
||||
-31.4
|
||||
-30.7
|
||||
-26.6
|
||||
-24.3
|
||||
-23.5
|
||||
-24
|
||||
-25.6
|
||||
-27.9
|
||||
-28.7
|
||||
-27.1
|
||||
-25.3
|
||||
-24.2
|
||||
-24.1
|
||||
-24.5
|
||||
-25.2
|
||||
-25.4
|
||||
-24.8
|
||||
-23.8
|
||||
-23.1
|
||||
-22.9
|
||||
-23.3
|
||||
-24.3
|
||||
-25.4
|
||||
-25.5
|
||||
-24
|
||||
-21.9
|
||||
-20.1
|
||||
-18.8
|
||||
-17.9
|
||||
-17.6
|
||||
-17.6
|
||||
-17.9
|
||||
-18.5
|
||||
-19
|
||||
-19.2
|
||||
-18.7
|
||||
-17.6
|
||||
-16.3
|
||||
-15
|
||||
-13.8
|
||||
-12.8
|
||||
-12.1
|
||||
-11.5
|
||||
-11
|
||||
-10.8
|
||||
-10.6
|
||||
-10.6
|
||||
-10.7
|
||||
-10.9
|
||||
-11.2
|
||||
-11.6
|
||||
-12.1
|
||||
-12.7
|
||||
-13.4
|
||||
-14.2
|
||||
-15.1
|
||||
-16.2
|
||||
-17.5
|
||||
-19
|
||||
-20.9
|
||||
-23.4
|
||||
-26.9
|
||||
-32.8
|
361
antenna/DB413-B.az
Normal file
361
antenna/DB413-B.az
Normal file
@@ -0,0 +1,361 @@
|
||||
0
|
||||
0 1.0000
|
||||
1 1.0000
|
||||
2 1.0000
|
||||
3 1.0000
|
||||
4 1.0000
|
||||
5 1.0000
|
||||
6 1.0000
|
||||
7 1.0000
|
||||
8 1.0000
|
||||
9 0.9772
|
||||
10 0.9772
|
||||
11 0.9772
|
||||
12 0.9772
|
||||
13 0.9772
|
||||
14 0.9772
|
||||
15 0.9772
|
||||
16 0.9772
|
||||
17 0.9550
|
||||
18 0.9550
|
||||
19 0.9550
|
||||
20 0.9550
|
||||
21 0.9550
|
||||
22 0.9333
|
||||
23 0.9333
|
||||
24 0.9333
|
||||
25 0.9333
|
||||
26 0.9120
|
||||
27 0.9120
|
||||
28 0.9120
|
||||
29 0.8913
|
||||
30 0.8913
|
||||
31 0.8913
|
||||
32 0.8710
|
||||
33 0.8710
|
||||
34 0.8710
|
||||
35 0.8511
|
||||
36 0.8511
|
||||
37 0.8318
|
||||
38 0.8318
|
||||
39 0.8318
|
||||
40 0.8128
|
||||
41 0.8128
|
||||
42 0.7943
|
||||
43 0.7943
|
||||
44 0.7762
|
||||
45 0.7762
|
||||
46 0.7586
|
||||
47 0.7586
|
||||
48 0.7413
|
||||
49 0.7244
|
||||
50 0.7244
|
||||
51 0.7079
|
||||
52 0.7079
|
||||
53 0.6918
|
||||
54 0.6918
|
||||
55 0.6761
|
||||
56 0.6607
|
||||
57 0.6457
|
||||
58 0.6457
|
||||
59 0.6310
|
||||
60 0.6166
|
||||
61 0.6166
|
||||
62 0.6026
|
||||
63 0.5888
|
||||
64 0.5754
|
||||
65 0.5623
|
||||
66 0.5623
|
||||
67 0.5495
|
||||
68 0.5370
|
||||
69 0.5248
|
||||
70 0.5129
|
||||
71 0.5012
|
||||
72 0.5012
|
||||
73 0.4898
|
||||
74 0.4786
|
||||
75 0.4677
|
||||
76 0.4571
|
||||
77 0.4467
|
||||
78 0.4365
|
||||
79 0.4266
|
||||
80 0.4169
|
||||
81 0.4074
|
||||
82 0.3981
|
||||
83 0.3890
|
||||
84 0.3715
|
||||
85 0.3631
|
||||
86 0.3548
|
||||
87 0.3467
|
||||
88 0.3388
|
||||
89 0.3311
|
||||
90 0.3236
|
||||
91 0.3162
|
||||
92 0.3020
|
||||
93 0.2951
|
||||
94 0.2884
|
||||
95 0.2818
|
||||
96 0.2754
|
||||
97 0.2630
|
||||
98 0.2570
|
||||
99 0.2512
|
||||
100 0.2455
|
||||
101 0.2399
|
||||
102 0.2291
|
||||
103 0.2239
|
||||
104 0.2188
|
||||
105 0.2138
|
||||
106 0.2089
|
||||
107 0.1995
|
||||
108 0.1950
|
||||
109 0.1905
|
||||
110 0.1862
|
||||
111 0.1820
|
||||
112 0.1738
|
||||
113 0.1698
|
||||
114 0.1660
|
||||
115 0.1622
|
||||
116 0.1585
|
||||
117 0.1549
|
||||
118 0.1514
|
||||
119 0.1479
|
||||
120 0.1445
|
||||
121 0.1413
|
||||
122 0.1380
|
||||
123 0.1349
|
||||
124 0.1318
|
||||
125 0.1288
|
||||
126 0.1288
|
||||
127 0.1259
|
||||
128 0.1230
|
||||
129 0.1202
|
||||
130 0.1202
|
||||
131 0.1175
|
||||
132 0.1175
|
||||
133 0.1148
|
||||
134 0.1148
|
||||
135 0.1122
|
||||
136 0.1122
|
||||
137 0.1096
|
||||
138 0.1096
|
||||
139 0.1096
|
||||
140 0.1072
|
||||
141 0.1072
|
||||
142 0.1072
|
||||
143 0.1072
|
||||
144 0.1072
|
||||
145 0.1072
|
||||
146 0.1072
|
||||
147 0.1072
|
||||
148 0.1047
|
||||
149 0.1047
|
||||
150 0.1072
|
||||
151 0.1072
|
||||
152 0.1072
|
||||
153 0.1072
|
||||
154 0.1072
|
||||
155 0.1072
|
||||
156 0.1072
|
||||
157 0.1072
|
||||
158 0.1072
|
||||
159 0.1072
|
||||
160 0.1072
|
||||
161 0.1096
|
||||
162 0.1096
|
||||
163 0.1096
|
||||
164 0.1096
|
||||
165 0.1096
|
||||
166 0.1096
|
||||
167 0.1096
|
||||
168 0.1096
|
||||
169 0.1122
|
||||
170 0.1122
|
||||
171 0.1122
|
||||
172 0.1122
|
||||
173 0.1122
|
||||
174 0.1122
|
||||
175 0.1122
|
||||
176 0.1122
|
||||
177 0.1122
|
||||
178 0.1122
|
||||
179 0.1122
|
||||
180 0.1122
|
||||
181 0.1122
|
||||
182 0.1122
|
||||
183 0.1122
|
||||
184 0.1122
|
||||
185 0.1122
|
||||
186 0.1122
|
||||
187 0.1122
|
||||
188 0.1122
|
||||
189 0.1122
|
||||
190 0.1122
|
||||
191 0.1122
|
||||
192 0.1096
|
||||
193 0.1096
|
||||
194 0.1096
|
||||
195 0.1096
|
||||
196 0.1096
|
||||
197 0.1096
|
||||
198 0.1096
|
||||
199 0.1096
|
||||
200 0.1072
|
||||
201 0.1072
|
||||
202 0.1072
|
||||
203 0.1072
|
||||
204 0.1072
|
||||
205 0.1072
|
||||
206 0.1072
|
||||
207 0.1072
|
||||
208 0.1072
|
||||
209 0.1072
|
||||
210 0.1072
|
||||
211 0.1047
|
||||
212 0.1047
|
||||
213 0.1072
|
||||
214 0.1072
|
||||
215 0.1072
|
||||
216 0.1072
|
||||
217 0.1072
|
||||
218 0.1072
|
||||
219 0.1072
|
||||
220 0.1072
|
||||
221 0.1096
|
||||
222 0.1096
|
||||
223 0.1096
|
||||
224 0.1122
|
||||
225 0.1122
|
||||
226 0.1148
|
||||
227 0.1148
|
||||
228 0.1175
|
||||
229 0.1175
|
||||
230 0.1202
|
||||
231 0.1202
|
||||
232 0.1230
|
||||
233 0.1259
|
||||
234 0.1288
|
||||
235 0.1288
|
||||
236 0.1318
|
||||
237 0.1349
|
||||
238 0.1380
|
||||
239 0.1413
|
||||
240 0.1445
|
||||
241 0.1479
|
||||
242 0.1514
|
||||
243 0.1549
|
||||
244 0.1585
|
||||
245 0.1622
|
||||
246 0.1660
|
||||
247 0.1698
|
||||
248 0.1738
|
||||
249 0.1820
|
||||
250 0.1862
|
||||
251 0.1905
|
||||
252 0.1950
|
||||
253 0.1995
|
||||
254 0.2089
|
||||
255 0.2138
|
||||
256 0.2188
|
||||
257 0.2239
|
||||
258 0.2291
|
||||
259 0.2399
|
||||
260 0.2455
|
||||
261 0.2512
|
||||
262 0.2570
|
||||
263 0.2630
|
||||
264 0.2754
|
||||
265 0.2818
|
||||
266 0.2884
|
||||
267 0.2951
|
||||
268 0.3020
|
||||
269 0.3162
|
||||
270 0.3236
|
||||
271 0.3311
|
||||
272 0.3388
|
||||
273 0.3467
|
||||
274 0.3548
|
||||
275 0.3631
|
||||
276 0.3715
|
||||
277 0.3890
|
||||
278 0.3981
|
||||
279 0.4074
|
||||
280 0.4169
|
||||
281 0.4266
|
||||
282 0.4365
|
||||
283 0.4467
|
||||
284 0.4571
|
||||
285 0.4677
|
||||
286 0.4786
|
||||
287 0.4898
|
||||
288 0.5012
|
||||
289 0.5012
|
||||
290 0.5129
|
||||
291 0.5248
|
||||
292 0.5370
|
||||
293 0.5495
|
||||
294 0.5623
|
||||
295 0.5623
|
||||
296 0.5754
|
||||
297 0.5888
|
||||
298 0.6026
|
||||
299 0.6166
|
||||
300 0.6166
|
||||
301 0.6310
|
||||
302 0.6457
|
||||
303 0.6457
|
||||
304 0.6607
|
||||
305 0.6761
|
||||
306 0.6918
|
||||
307 0.6918
|
||||
308 0.7079
|
||||
309 0.7079
|
||||
310 0.7244
|
||||
311 0.7244
|
||||
312 0.7413
|
||||
313 0.7586
|
||||
314 0.7586
|
||||
315 0.7762
|
||||
316 0.7762
|
||||
317 0.7943
|
||||
318 0.7943
|
||||
319 0.8128
|
||||
320 0.8128
|
||||
321 0.8318
|
||||
322 0.8318
|
||||
323 0.8318
|
||||
324 0.8511
|
||||
325 0.8511
|
||||
326 0.8710
|
||||
327 0.8710
|
||||
328 0.8710
|
||||
329 0.8913
|
||||
330 0.8913
|
||||
331 0.8913
|
||||
332 0.9120
|
||||
333 0.9120
|
||||
334 0.9120
|
||||
335 0.9333
|
||||
336 0.9333
|
||||
337 0.9333
|
||||
338 0.9333
|
||||
339 0.9550
|
||||
340 0.9550
|
||||
341 0.9550
|
||||
342 0.9550
|
||||
343 0.9550
|
||||
344 0.9772
|
||||
345 0.9772
|
||||
346 0.9772
|
||||
347 0.9772
|
||||
348 0.9772
|
||||
349 0.9772
|
||||
350 0.9772
|
||||
351 0.9772
|
||||
352 1.0000
|
||||
353 1.0000
|
||||
354 1.0000
|
||||
355 1.0000
|
||||
356 1.0000
|
||||
357 1.0000
|
||||
358 1.0000
|
||||
359 1.0000
|
102
antenna/DB413-B.el
Normal file
102
antenna/DB413-B.el
Normal file
@@ -0,0 +1,102 @@
|
||||
0 0
|
||||
-10 0.0398
|
||||
-9 0.0257
|
||||
-8 0.0063
|
||||
-7 0.0045
|
||||
-6 0.0479
|
||||
-5 0.1585
|
||||
-4 0.3388
|
||||
-3 0.5623
|
||||
-2 0.7943
|
||||
-1 0.9550
|
||||
0 1.0000
|
||||
1 0.9333
|
||||
2 0.7413
|
||||
3 0.5129
|
||||
4 0.2884
|
||||
5 0.1175
|
||||
6 0.0251
|
||||
7 0.0001
|
||||
8 0.0141
|
||||
9 0.0363
|
||||
10 0.0468
|
||||
11 0.0407
|
||||
12 0.0245
|
||||
13 0.0095
|
||||
14 0.0021
|
||||
15 0.0030
|
||||
16 0.0079
|
||||
17 0.0123
|
||||
18 0.0129
|
||||
19 0.0102
|
||||
20 0.0065
|
||||
21 0.0035
|
||||
22 0.0023
|
||||
23 0.0029
|
||||
24 0.0045
|
||||
25 0.0060
|
||||
26 0.0071
|
||||
27 0.0072
|
||||
28 0.0062
|
||||
29 0.0044
|
||||
30 0.0025
|
||||
31 0.0014
|
||||
32 0.0019
|
||||
33 0.0039
|
||||
34 0.0065
|
||||
35 0.0083
|
||||
36 0.0085
|
||||
37 0.0066
|
||||
38 0.0036
|
||||
39 0.0010
|
||||
40 0.0003
|
||||
41 0.0020
|
||||
42 0.0056
|
||||
43 0.0098
|
||||
44 0.0126
|
||||
45 0.0129
|
||||
46 0.0107
|
||||
47 0.0068
|
||||
48 0.0028
|
||||
49 0.0004
|
||||
50 0.0004
|
||||
51 0.0029
|
||||
52 0.0071
|
||||
53 0.0112
|
||||
54 0.0145
|
||||
55 0.0151
|
||||
56 0.0132
|
||||
57 0.0095
|
||||
58 0.0050
|
||||
59 0.0014
|
||||
60 0.0002
|
||||
61 0.0024
|
||||
62 0.0085
|
||||
63 0.0182
|
||||
64 0.0316
|
||||
65 0.0457
|
||||
66 0.0617
|
||||
67 0.0759
|
||||
68 0.0871
|
||||
69 0.0977
|
||||
70 0.1047
|
||||
71 0.1072
|
||||
72 0.1072
|
||||
73 0.1023
|
||||
74 0.0977
|
||||
75 0.0891
|
||||
76 0.0813
|
||||
77 0.0708
|
||||
78 0.0617
|
||||
79 0.0525
|
||||
80 0.0437
|
||||
81 0.0347
|
||||
82 0.0275
|
||||
83 0.0209
|
||||
84 0.0151
|
||||
85 0.0105
|
||||
86 0.0066
|
||||
87 0.0036
|
||||
88 0.0016
|
||||
89 0.0004
|
||||
90 0.0001
|
3
color/black.scf
Normal file
3
color/black.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 0, 0, 0
|
||||
0: 0, 0, 0
|
3
color/blue.scf
Normal file
3
color/blue.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 0, 0, 255
|
||||
0: 0, 0, 255
|
3
color/cyan.scf
Normal file
3
color/cyan.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 0, 255, 255
|
||||
0: 0, 255, 255
|
3
color/green.scf
Normal file
3
color/green.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 0, 255, 0
|
||||
0: 0, 255, 0
|
3
color/magenta.scf
Normal file
3
color/magenta.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 255, 0, 255
|
||||
0: 255, 0, 255
|
16
color/rainbow.dcf
Normal file
16
color/rainbow.dcf
Normal file
@@ -0,0 +1,16 @@
|
||||
+0: 255, 0, 0
|
||||
-10: 255, 128, 0
|
||||
-20: 255, 165, 0
|
||||
-30: 255, 206, 0
|
||||
-40: 255, 255, 0
|
||||
-50: 184, 255, 0
|
||||
-60: 0, 255, 0
|
||||
-70: 0, 208, 0
|
||||
-80: 0, 196, 196
|
||||
-90: 0, 148, 255
|
||||
-100: 80, 80, 255
|
||||
-110: 0, 38, 255
|
||||
-120: 142, 63, 255
|
||||
-130: 196, 54, 255
|
||||
-140: 255, 0, 255
|
||||
-150: 255, 194, 204
|
13
color/rainbow.scf
Normal file
13
color/rainbow.scf
Normal file
@@ -0,0 +1,13 @@
|
||||
128: 255, 0, 0
|
||||
118: 255, 165, 0
|
||||
108: 255, 206, 0
|
||||
98: 255, 255, 0
|
||||
88: 184, 255, 0
|
||||
78: 0, 255, 0
|
||||
68: 0, 208, 0
|
||||
58: 0, 196, 196
|
||||
48: 0, 148, 255
|
||||
38: 80, 80, 255
|
||||
28: 0, 38, 255
|
||||
18: 142, 63, 255
|
||||
8: 140, 0, 128
|
3
color/red.scf
Normal file
3
color/red.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 255, 0, 0
|
||||
0: 255, 0, 0
|
3
color/yellow.scf
Normal file
3
color/yellow.scf
Normal file
@@ -0,0 +1,3 @@
|
||||
200: 255, 255, 255
|
||||
59: 255, 255, 0
|
||||
0: 255, 255, 0
|
0
data/51:52:0:1-hd.sdf
Executable file → Normal file
0
data/51:52:0:1-hd.sdf
Executable file → Normal file
0
data/51:52:0:1.sdf
Executable file → Normal file
0
data/51:52:0:1.sdf
Executable file → Normal file
Binary file not shown.
3606
data/N051W001_AVE_DSM.tif.asc
Normal file
3606
data/N051W001_AVE_DSM.tif.asc
Normal file
File diff suppressed because one or more lines are too long
11
data/test.udt
Normal file
11
data/test.udt
Normal file
@@ -0,0 +1,11 @@
|
||||
// Put a giant 5000 foot wall in the middle of Lake Michigan near Chicago!
|
||||
42.280056,-87.772222,5000
|
||||
42.281056,-87.772222,5000
|
||||
42.282056,-87.772222,5000
|
||||
42.283056,-87.772222,5000
|
||||
42.284056,-87.772222,5000
|
||||
42.285056,-87.772222,5000
|
||||
42.286056,-87.772222,5000
|
||||
42.287056,-87.772222,5000
|
||||
42.288056,-87.772222,5000
|
||||
42.289056,-87.772222,5000
|
42
genkmz.sh
Executable file
42
genkmz.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
while read line
|
||||
do
|
||||
echo $line
|
||||
if [[ $line == Writing* ]]
|
||||
then
|
||||
while IFS='"' read -ra writingline
|
||||
do
|
||||
# echo "writingline: ${writingline}"
|
||||
filename=${writingline[1]%.*}
|
||||
# echo "filename: ${filename}"
|
||||
done <<< $line
|
||||
fi
|
||||
if [[ $line == \|* ]]
|
||||
then
|
||||
while IFS='|' read -ra coords
|
||||
do
|
||||
cat << EOF > doc.kml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<GroundOverlay>
|
||||
<name>${filename}</name>
|
||||
<Icon>
|
||||
<href>${filename}.png</href>
|
||||
</Icon>
|
||||
<LatLonBox>
|
||||
<north>${coords[1]}</north>
|
||||
<east>${coords[2]}</east>
|
||||
<south>${coords[3]}</south>
|
||||
<west>${coords[4]}</west>
|
||||
</LatLonBox>
|
||||
</GroundOverlay>
|
||||
</kml>
|
||||
EOF
|
||||
done <<< $line
|
||||
fi
|
||||
done
|
||||
#echo "filename: ${filename}"
|
||||
zip "${filename}" "${filename}.png" "doc.kml"
|
||||
mv "${filename}".zip "${filename}".kmz
|
||||
rm "doc.kml"
|
||||
echo Generated "${filename}".kmz
|
18
runsig.sh
Executable file
18
runsig.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
echo Usage:
|
||||
echo $0 -lat 46.4879 -lon -123.2144 -txh 60 -f 145 -erp 30 -R 80 -o outfile | ./genkmz.sh
|
||||
echo The last argument must be the output file name.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for name; do true; done
|
||||
|
||||
# This script should contain options common to every run on the target system.
|
||||
|
||||
#time ./signalserverHD -sdf /mnt/data -pm 1 -rxh 6 -te 3 -cl 5 -pe 2 -dbg $@ 2>&1
|
||||
time ./signalserver -sdf /mnt/data -pm 1 -rxh 6 -te 3 -cl 5 -pe 2 -dbg $@ 2>&1
|
||||
# to resize, add: -resize 7000x7000\>
|
||||
convert $name.ppm -transparent white $name.png
|
77
src/Makefile
Normal file
77
src/Makefile
Normal file
@@ -0,0 +1,77 @@
|
||||
SHELL = /bin/sh
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -Wall -O3 -s -ffast-math -DCROPPING
|
||||
CXXFLAGS = -Wall -O3 -s -ffast-math
|
||||
LIBS = -lm -lpthread -ldl -lbz2 -lz
|
||||
|
||||
INSTALL_PATH = ..
|
||||
VPATH = models
|
||||
objects = main.o cost.o ecc33.o ericsson.o fspl.o hata.o itwom3.0.o \
|
||||
los.o sui.o pel.o egli.o soil.o inputs.o outputs.o image.o \
|
||||
image-ppm.o tiles.o
|
||||
|
||||
GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 1)
|
||||
GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 2)
|
||||
GCC_VER_OK := $(shell test $(GCC_MAJOR) -ge 4 && \
|
||||
test $(GCC_MINOR) -ge 7 && \
|
||||
echo 1)
|
||||
|
||||
#ifneq "$(GCC_VER_OK)" "1"
|
||||
#error:
|
||||
# @echo "Requires GCC version >= 4.7"
|
||||
# @exit
|
||||
#endif
|
||||
|
||||
%.o : %.cc
|
||||
@echo -e " CXX\t$@"
|
||||
@$ $(CXX) $(CXXFLAGS) -c $<
|
||||
|
||||
%.o : %.c
|
||||
@echo -e " CC\t$@"
|
||||
@$ $(CC) $(CFLAGS) -c $<
|
||||
|
||||
signalserver: $(objects)
|
||||
@echo -e " LNK\t$@"
|
||||
@$(CXX) $(objects) -o $@ ${LIBS}
|
||||
@echo -e " SYMLNK\tsignalserverHD -> $@"
|
||||
@ln -sf $@ signalserverHD
|
||||
@echo -e " SYMLNK\tsignalserverLIDAR -> $@"
|
||||
@ln -sf $@ signalserverLIDAR
|
||||
|
||||
main.o: main.cc common.h inputs.hh outputs.hh itwom3.0.hh los.hh pel.hh \
|
||||
image.hh
|
||||
|
||||
inputs.o: inputs.cc common.h main.hh tiles.hh
|
||||
|
||||
outputs.o: outputs.cc common.h main.hh inputs.hh cost.hh ecc33.hh ericsson.hh \
|
||||
fspl.hh hata.hh itwom3.0.hh sui.hh image.hh
|
||||
|
||||
image.o: image.cc image-ppm.o image.hh image-ppm.hh
|
||||
|
||||
image-ppm.o: image-ppm.cc image.hh
|
||||
|
||||
los.o: los.cc los.hh main.hh cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
|
||||
itwom3.0.hh sui.hh pel.hh egli.hh soil.hh
|
||||
|
||||
tiles.o: tiles.cc tiles.hh common.h
|
||||
|
||||
|
||||
testmodels.o: testmodels.cc cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
|
||||
egli.hh sui.hh itwom3.0.hh
|
||||
|
||||
testmodels: testmodels.o cost.o ecc33.o ericsson.o fspl.o hata.o egli.o sui.o itwom3.0.o
|
||||
@echo -e " LNK\t$@"
|
||||
@$(CXX) testmodels.o cost.o ecc33.o ericsson.o fspl.o hata.o egli.o \
|
||||
sui.o itwom3.0.o -o $@ ${LIBS}
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(objects) signalserver signalserverHD signalserverLIDAR testmodels
|
||||
|
||||
all: signalserver
|
||||
|
||||
install: all
|
||||
cp -a signalserver signalserverHD signalserverLIDAR $(INSTALL_PATH)
|
||||
|
131
src/common.h
Normal file
131
src/common.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#define GAMMA 2.5
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.141592653589793
|
||||
#endif
|
||||
|
||||
#ifndef TWOPI
|
||||
#define TWOPI 6.283185307179586
|
||||
#endif
|
||||
|
||||
#ifndef HALFPI
|
||||
#define HALFPI 1.570796326794896
|
||||
#endif
|
||||
|
||||
#define DEG2RAD 1.74532925199e-02
|
||||
#define EARTHRADIUS 20902230.97
|
||||
#define METERS_PER_MILE 1609.344
|
||||
#define METERS_PER_FOOT 0.3048
|
||||
#define KM_PER_MILE 1.609344
|
||||
#define FEET_PER_MILE 5280.0
|
||||
#define FOUR_THIRDS 1.3333333333333
|
||||
|
||||
#define MAX(x,y)((x)>(y)?(x):(y))
|
||||
|
||||
struct dem {
|
||||
float min_north;
|
||||
float max_north;
|
||||
float min_west;
|
||||
float max_west;
|
||||
int max_el;
|
||||
int min_el;
|
||||
short **data;
|
||||
unsigned char **mask;
|
||||
unsigned char **signal;
|
||||
};
|
||||
|
||||
struct site {
|
||||
double lat;
|
||||
double lon;
|
||||
float alt;
|
||||
char name[50];
|
||||
char filename[255];
|
||||
};
|
||||
|
||||
struct path {
|
||||
double *lat;
|
||||
double *lon;
|
||||
double *elevation;
|
||||
double *distance;
|
||||
int length;
|
||||
};
|
||||
|
||||
struct LR {
|
||||
double eps_dielect;
|
||||
double sgm_conductivity;
|
||||
double eno_ns_surfref;
|
||||
double frq_mhz;
|
||||
double conf;
|
||||
double rel;
|
||||
double erp;
|
||||
int radio_climate;
|
||||
int pol;
|
||||
float antenna_pattern[361][1001];
|
||||
};
|
||||
|
||||
struct region {
|
||||
unsigned char color[128][3];
|
||||
int level[128];
|
||||
int levels;
|
||||
};
|
||||
|
||||
extern int MAXPAGES;
|
||||
extern int ARRAYSIZE;
|
||||
extern int IPPD;
|
||||
|
||||
extern double min_north;
|
||||
extern double max_north;
|
||||
extern double min_west;
|
||||
extern double max_west;
|
||||
extern int ippd;
|
||||
extern int MAXRAD;
|
||||
extern int mpi;
|
||||
extern int max_elevation;
|
||||
extern int min_elevation;
|
||||
extern int contour_threshold;
|
||||
extern int loops;
|
||||
extern int jgets;
|
||||
extern int width;
|
||||
extern int height;
|
||||
|
||||
extern double earthradius;
|
||||
extern double north;
|
||||
extern double east;
|
||||
extern double south;
|
||||
extern double west;
|
||||
extern double max_range;
|
||||
extern double dpp;
|
||||
extern double ppd;
|
||||
extern double yppd;
|
||||
extern double fzone_clearance;
|
||||
extern double clutter;
|
||||
extern double dBm;
|
||||
extern double loss;
|
||||
extern double field_strength;
|
||||
extern __thread double *elev;
|
||||
extern double westoffset;
|
||||
extern double eastoffset;
|
||||
extern double delta;
|
||||
extern double cropLat;
|
||||
extern double cropLon;
|
||||
|
||||
extern char string[];
|
||||
extern char sdf_path[];
|
||||
extern char gpsav;
|
||||
|
||||
extern unsigned char got_elevation_pattern;
|
||||
extern unsigned char got_azimuth_pattern;
|
||||
extern unsigned char metric;
|
||||
extern unsigned char dbm;
|
||||
|
||||
extern struct dem *dem;
|
||||
extern __thread struct path path;
|
||||
extern struct LR LR;
|
||||
extern struct region region;
|
||||
|
||||
extern int debug;
|
||||
|
||||
#endif /* _COMMON_H_ */
|
59
src/image-ppm.cc
Normal file
59
src/image-ppm.cc
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "image.hh"
|
||||
|
||||
int ppm_init(image_ctx_t *ctx){
|
||||
size_t buf_size;
|
||||
|
||||
/* Perform simple sanity checking */
|
||||
if(ctx->canvas != NULL)
|
||||
return EINVAL;
|
||||
ctx->model = IMAGE_RGB; //Override this as we only support RGB
|
||||
ctx->format = IMAGE_PPM;
|
||||
ctx->extension = (char*)".ppm";
|
||||
|
||||
buf_size = ctx->width * ctx->height * RGB_SIZE;
|
||||
|
||||
/* Allocate the canvas buffer */
|
||||
ctx->canvas = (uint8_t*) calloc(buf_size,sizeof(uint8_t));
|
||||
ctx->next_pixel = ctx->canvas;
|
||||
if(ctx->canvas == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ppm_add_pixel(image_ctx_t *ctx,const uint8_t r,const uint8_t g,const uint8_t b,const uint8_t a){
|
||||
register uint8_t* next;
|
||||
|
||||
next = ctx->next_pixel;
|
||||
|
||||
next[0] = r;
|
||||
next[1] = g;
|
||||
next[2] = b;
|
||||
|
||||
ctx->next_pixel += 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ppm_get_pixel(image_ctx_t *ctx,const size_t x,const size_t y,const uint8_t *r,const uint8_t *g,const uint8_t *b,const uint8_t *a){
|
||||
/* STUB */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ppm_write(image_ctx_t *ctx, FILE* fd){
|
||||
size_t written;
|
||||
size_t count;
|
||||
|
||||
count = ctx->width * ctx->height * RGB_SIZE;
|
||||
|
||||
fprintf(fd, "P6\n%zu %zu\n255\n", ctx->width, ctx->height);
|
||||
written = fwrite(ctx->canvas,sizeof(uint8_t),count,fd);
|
||||
if(written < count)
|
||||
return EPIPE;
|
||||
|
||||
return 0;
|
||||
}
|
23
src/image-ppm.hh
Normal file
23
src/image-ppm.hh
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _IMAGE_PPM_HH
|
||||
#define _IMAGE_PPM_HH
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "image.hh"
|
||||
|
||||
int ppm_init(image_ctx_t *ctx);
|
||||
int ppm_add_pixel(image_ctx_t *ctx,const uint8_t r,const uint8_t g,const uint8_t b,const uint8_t a);
|
||||
int ppm_get_pixel(image_ctx_t *ctx,const size_t x,const size_t y,const uint8_t *r,const uint8_t *g,const uint8_t *b,const uint8_t *a);
|
||||
int ppm_write(image_ctx_t *ctx, FILE* fd);
|
||||
|
||||
image_dispatch_table_t ppm_dt = {\
|
||||
.init = ppm_init, \
|
||||
.add_pixel = ppm_add_pixel, \
|
||||
.set_pixel = NULL, \
|
||||
.get_pixel = ppm_get_pixel, \
|
||||
.write = ppm_write, \
|
||||
.free = NULL
|
||||
};
|
||||
|
||||
#endif
|
275
src/image.cc
Normal file
275
src/image.cc
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Generic image output handling. This feature allows
|
||||
* for extensible image output formats and permits for
|
||||
* cleaner image rendering code in the model generation
|
||||
* routines by moving all of the file-format specific
|
||||
* logic to be handled here.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include "image.hh"
|
||||
#include "image-ppm.hh"
|
||||
|
||||
int get_dt(image_dispatch_table_t *dt, int format);
|
||||
int load_library(image_dispatch_table_t *dt);
|
||||
|
||||
#define DISPATCH_TABLE(ctx) ((image_dispatch_table_t*)(ctx)->_dt)
|
||||
|
||||
static int default_format = IMAGE_PPM;
|
||||
char *dynamic_backend = NULL;
|
||||
|
||||
/*
|
||||
* image_set_format
|
||||
* Changes the default format for the next
|
||||
* uninitialized image canvas
|
||||
*/
|
||||
int image_set_format(int format){
|
||||
if(format <= IMAGE_DEFAULT || format >= IMAGE_FORMAT_MAX)
|
||||
return EINVAL;
|
||||
default_format = format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* image_init
|
||||
* Initialize an image context. Must be called
|
||||
* before attempting to write any image data
|
||||
*/
|
||||
int image_init(image_ctx_t *ctx, \
|
||||
const size_t width, \
|
||||
const size_t height, \
|
||||
const int model, \
|
||||
const int format) {
|
||||
|
||||
int success = 0;
|
||||
image_dispatch_table_t *dt;
|
||||
|
||||
/* Perform some sanity checking on provided arguments */
|
||||
if(ctx == NULL)
|
||||
return EINVAL;
|
||||
if(width == 0 || height == 0)
|
||||
return EINVAL;
|
||||
if(model < 0 || model > IMAGE_MODEL_MAX)
|
||||
return EINVAL;
|
||||
if(format >= IMAGE_FORMAT_MAX || (format == IMAGE_LIBRARY && dynamic_backend == NULL))
|
||||
return EINVAL;
|
||||
|
||||
memset(ctx,0x00,sizeof(image_ctx_t));
|
||||
|
||||
/* Assign the initialize values to the processing context */
|
||||
ctx->width = width;
|
||||
ctx->height = height;
|
||||
ctx->model = model;
|
||||
if(format == IMAGE_DEFAULT)
|
||||
ctx->format = default_format;
|
||||
else
|
||||
ctx->format = format;
|
||||
|
||||
/* Get the dispatch table for this image format */
|
||||
dt = (image_dispatch_table_t *) calloc(1,sizeof(image_dispatch_table_t));
|
||||
if(dt == NULL){
|
||||
fprintf(stderr,"Error allocating dispatch table\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
success = get_dt(dt,ctx->format);
|
||||
if(success != 0){
|
||||
fprintf(stderr,"Error locating dispatch table\n");
|
||||
free(dt);
|
||||
return success;
|
||||
}
|
||||
ctx->_dt = (void*)dt;
|
||||
|
||||
/* Call the format-specific initialization function */
|
||||
success = dt->init(ctx);
|
||||
if(success != 0){
|
||||
fprintf(stderr,"Error initializing image context\n");
|
||||
free(dt);
|
||||
return success;
|
||||
}
|
||||
|
||||
ctx->initialized = 1;
|
||||
|
||||
return success;
|
||||
}
|
||||
/*
|
||||
* image_add_pixel, image_set_pixel, image_get_pixel, image_write, image_free
|
||||
* Various setters ad getters for assigning pixel data. image_write
|
||||
* takes an open file handle and writes image data to it.
|
||||
* These functions simply wrap the underlying format-specific functions
|
||||
*/
|
||||
int image_add_pixel(image_ctx_t *ctx, const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a){
|
||||
if(ctx->initialized != 1) return EINVAL;
|
||||
return DISPATCH_TABLE(ctx)->add_pixel(ctx,r,g,b,a);
|
||||
}
|
||||
int image_set_pixel(image_ctx_t *ctx, const size_t x, const size_t y, const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a){
|
||||
size_t block_size;
|
||||
if(ctx->initialized != 1) return EINVAL;
|
||||
/* Image format handlers have the option to specify a _set_pixel handler */
|
||||
if(DISPATCH_TABLE(ctx)->set_pixel != NULL){
|
||||
return DISPATCH_TABLE(ctx)->set_pixel(ctx,x,y,r,g,b,a);
|
||||
}
|
||||
block_size = ctx->model == IMAGE_RGB ? RGB_SIZE : RGBA_SIZE;
|
||||
ctx->next_pixel = ctx->canvas + PIXEL_OFFSET(x,y,ctx->width,block_size);
|
||||
return DISPATCH_TABLE(ctx)->add_pixel(ctx,r,g,b,a);
|
||||
}
|
||||
int image_get_pixel(image_ctx_t *ctx, const size_t x, const size_t y, const uint8_t *r, const uint8_t *g, const uint8_t *b, const uint8_t *a){
|
||||
if(ctx->initialized != 1) return EINVAL;
|
||||
if(DISPATCH_TABLE(ctx)->get_pixel != NULL)
|
||||
return DISPATCH_TABLE(ctx)->get_pixel(ctx,x,y,r,g,b,a);
|
||||
return ENOSYS;
|
||||
}
|
||||
int image_write(image_ctx_t *ctx, FILE *fd){
|
||||
if(ctx->initialized != 1) return EINVAL;
|
||||
return DISPATCH_TABLE(ctx)->write(ctx,fd);
|
||||
}
|
||||
void image_free(image_ctx_t *ctx){
|
||||
if(ctx->initialized != 1) return;
|
||||
if(DISPATCH_TABLE(ctx)->free != NULL){
|
||||
DISPATCH_TABLE(ctx)->free(ctx);
|
||||
}
|
||||
if(ctx->canvas != NULL) free(ctx->canvas);
|
||||
}
|
||||
|
||||
/*
|
||||
* image_get_filename
|
||||
* Creates an appropriate file name using data supplied
|
||||
* by the user. If the extension is already correct, return
|
||||
* that; if not append if there is space
|
||||
*/
|
||||
int image_get_filename(image_ctx_t *ctx, char *out, size_t len_out, char *in){
|
||||
size_t len_src;
|
||||
size_t len_ext;
|
||||
int success = 0;
|
||||
|
||||
if(ctx->initialized != 1)
|
||||
return EINVAL;
|
||||
|
||||
/* Get various lengths */
|
||||
len_src = strlen(in);
|
||||
len_ext = strlen(ctx->extension);
|
||||
|
||||
if(len_src == 0){
|
||||
in = (char*)"output";
|
||||
len_src = 6;
|
||||
}
|
||||
|
||||
if(len_src > len_ext && strcmp(in+len_src-len_ext,ctx->extension) == 0){
|
||||
/* Already has correct extension and fits in buffer */
|
||||
if(len_src < len_out)
|
||||
strncpy(in,out,len_out);
|
||||
else
|
||||
success = ENOMEM;
|
||||
}else if(len_src > len_ext){
|
||||
/* Doesn't have correct extension and fits */
|
||||
if(len_src + len_ext < len_out){
|
||||
strncpy(out,in,len_out);
|
||||
strncat(out,ctx->extension,len_out);
|
||||
}else
|
||||
success = ENOMEM;
|
||||
}else{
|
||||
/* The input buffer plus an extension cannot fit in the output buffer */
|
||||
fprintf(stderr,"Error building image output filename\n");
|
||||
success = ENOMEM;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_dt
|
||||
* Load the dispatch table for the specified image
|
||||
* format. Currently only pixmap supported.
|
||||
*/
|
||||
int get_dt(image_dispatch_table_t *dt, int format){
|
||||
int success = 0;
|
||||
|
||||
memset((void*)dt,0x00,sizeof(image_dispatch_table_t));
|
||||
switch(format){
|
||||
case IMAGE_PPM:
|
||||
*dt = ppm_dt;
|
||||
break;
|
||||
case IMAGE_LIBRARY:
|
||||
success = load_library(dt);
|
||||
break;
|
||||
default:
|
||||
success = EINVAL;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* ==WARNING==: Here be dragons!
|
||||
* Experimantal features beyond this point.
|
||||
* Only use if you are sure you know what you
|
||||
* are doing!
|
||||
*/
|
||||
|
||||
/*
|
||||
* image_set_library
|
||||
* Set the library to use for generating images
|
||||
*/
|
||||
int image_set_library(char *library){
|
||||
char *libname;
|
||||
size_t length;
|
||||
|
||||
length = strlen(library) + 1;
|
||||
libname = (char*)calloc(length,sizeof(char));
|
||||
if(libname == NULL)
|
||||
return ENOMEM;
|
||||
strncpy(libname,library,length);
|
||||
|
||||
dynamic_backend = libname;
|
||||
default_format = IMAGE_LIBRARY;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* image_get_library
|
||||
* Returns the current saved image rendering
|
||||
* library
|
||||
*/
|
||||
char* image_get_library(){
|
||||
return dynamic_backend;
|
||||
}
|
||||
|
||||
/*
|
||||
* load_library
|
||||
* External image processing: experimental feature
|
||||
* Load an external library to perform image processing
|
||||
* It must be a custom compatible library
|
||||
*/
|
||||
int load_library(image_dispatch_table_t *dt){
|
||||
void *hndl;
|
||||
int success = 0;
|
||||
|
||||
/* Validate object file */
|
||||
if(dynamic_backend == NULL || strlen(dynamic_backend) == 0){
|
||||
fprintf(stderr,"Custom image processor requested without specification\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Load shared object and locate required exports */
|
||||
hndl = dlopen(dynamic_backend,RTLD_LAZY);
|
||||
if(hndl == NULL){
|
||||
fprintf(stderr,"Error loading shared object\n");
|
||||
return EINVAL;
|
||||
}
|
||||
/* Perform symbol lookup */
|
||||
if((dt->init = (_init*)dlsym(hndl,"lib_init")) == NULL ||
|
||||
(dt->add_pixel = (_add_pixel*)dlsym(hndl,"lib_add_pixel")) == NULL ||
|
||||
(dt->write = (_write*)dlsym(hndl,"lib_write")) == NULL){
|
||||
fprintf(stderr,"Invalid image processing module specified\n\t%s",dlerror());
|
||||
success = EINVAL;
|
||||
(void) dlclose(hndl);
|
||||
}
|
||||
/* Lookup optional symbols, these can return NULL */
|
||||
if(success == 0){
|
||||
dt->get_pixel = (_get_pixel*)dlsym(hndl,"lib_get_pixel");
|
||||
dt->set_pixel = (_set_pixel*)dlsym(hndl,"lib_set_pixel");
|
||||
dt->free = (_free*)dlsym(hndl,"lib_free");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
63
src/image.hh
Normal file
63
src/image.hh
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef _IMAGE_HH_
|
||||
#define _IMAGE_HH_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RGB_SIZE 3
|
||||
#define RGBA_SIZE 4
|
||||
|
||||
enum _image_format{ IMAGE_DEFAULT = 0, \
|
||||
IMAGE_PPM, \
|
||||
IMAGE_LIBRARY, \
|
||||
IMAGE_FORMAT_MAX \
|
||||
};
|
||||
|
||||
enum _image_model{ IMAGE_RGB, \
|
||||
IMAGE_RGBA, \
|
||||
IMAGE_MODEL_MAX
|
||||
};
|
||||
|
||||
typedef struct _image_ctx{
|
||||
size_t width;
|
||||
size_t height;
|
||||
int model;
|
||||
int format;
|
||||
uint8_t *canvas;
|
||||
uint8_t *next_pixel;
|
||||
uint32_t initialized;
|
||||
char *extension;
|
||||
void *_dt;
|
||||
} image_ctx_t, *pimage_ctx_t;
|
||||
|
||||
typedef int _init(image_ctx_t*);
|
||||
typedef int _add_pixel(image_ctx_t*,const uint8_t,const uint8_t,const uint8_t,const uint8_t);
|
||||
typedef int _set_pixel(image_ctx_t*,const size_t,const size_t,const uint8_t,const uint8_t,const uint8_t,const uint8_t);
|
||||
typedef int _get_pixel(image_ctx_t*,const size_t,const size_t,const uint8_t*,const uint8_t*,const uint8_t*,const uint8_t*);
|
||||
typedef int _write(image_ctx_t*,FILE*);
|
||||
typedef void _free(image_ctx_t*);
|
||||
|
||||
typedef struct _image_dispatch_table{
|
||||
_init *init;
|
||||
_add_pixel *add_pixel;
|
||||
_set_pixel *set_pixel;
|
||||
_get_pixel *get_pixel;
|
||||
_write *write;
|
||||
_free *free;
|
||||
} image_dispatch_table_t;
|
||||
|
||||
int image_set_format(int);
|
||||
int image_init(image_ctx_t*, const size_t, const size_t, const int, const int);
|
||||
int image_add_pixel(image_ctx_t* ctx, const uint8_t, const uint8_t, const uint8_t, const uint8_t);
|
||||
int image_set_pixel(image_ctx_t* ctx, const size_t, const size_t, const uint8_t, const uint8_t, const uint8_t, const uint8_t);
|
||||
int image_get_pixel(image_ctx_t* ctx,const size_t,const size_t, uint8_t const*, uint8_t const*, uint8_t const*, uint8_t const*);
|
||||
int image_get_filename(image_ctx_t*, char*, size_t, char*);
|
||||
int image_write(image_ctx_t*, FILE*);
|
||||
void image_free(image_ctx_t*);
|
||||
int image_set_library(char*);
|
||||
|
||||
#define ADD_PIXEL(ctx,r,g,b) image_add_pixel((ctx),(r),(g),(b),0xff)
|
||||
#define ADD_PIXELA(ctx,r,g,b,a) image_add_pixel((ctx),(r),(g),(b),(a))
|
||||
|
||||
#define PIXEL_OFFSET(x,y,width,pixel_size) (((x) * (pixel_size)) + ((width) * (pixel_size) * (y)))
|
||||
|
||||
#endif
|
2514
src/inputs.cc
Normal file
2514
src/inputs.cc
Normal file
File diff suppressed because it is too large
Load Diff
29
src/inputs.hh
Normal file
29
src/inputs.hh
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _INPUTS_HH_
|
||||
#define _INPUTS_HH_
|
||||
|
||||
#include "common.h"
|
||||
extern char scf_file[255];
|
||||
|
||||
/* Resample input tiles to new resolution */
|
||||
int resample_data(int scaling_factor);
|
||||
int resize_data(int resolution);
|
||||
|
||||
int LoadSDF_SDF(char *name, int winfiles);
|
||||
char *BZfgets(char *output, BZFILE *bzfd, unsigned length);
|
||||
int LoadSDF_GZ(char *name);
|
||||
char *GZfgets(char *output, gzFile gzfd, unsigned length);
|
||||
int LoadSDF_BZ(char *name);
|
||||
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);
|
||||
int LoadTopoData(double max_lon, double min_lon, double max_lat, double min_lat);
|
||||
int LoadUDT(char *filename);
|
||||
int loadLIDAR(char *filename, int resample);
|
||||
int loadClutter(char *filename, double radius, struct site tx);
|
||||
int averageHeight(int h, int w, int x, int y);
|
||||
static const char AZ_FILE_SUFFIX[] = ".az";
|
||||
static const char EL_FILE_SUFFIX[] = ".el";
|
||||
|
||||
#endif /* _INPUTS_HH_ */
|
2057
src/main.cc
Normal file
2057
src/main.cc
Normal file
File diff suppressed because it is too large
Load Diff
33
src/main.hh
Normal file
33
src/main.hh
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _MAIN_HH_
|
||||
#define _MAIN_HH_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int ReduceAngle(double angle);
|
||||
double LonDiff(double lon1, double lon2);
|
||||
void *dec2dms(double decimal, char *string);
|
||||
int PutMask(double lat, double lon, int value);
|
||||
int OrMask(double lat, double lon, int value);
|
||||
int GetMask(double lat, double lon);
|
||||
void PutSignal(double lat, double lon, unsigned char signal);
|
||||
unsigned char GetSignal(double lat, double lon);
|
||||
double GetElevation(struct site location);
|
||||
int AddElevation(double lat, double lon, double height, int size);
|
||||
double Distance(struct site site1, struct site site2);
|
||||
double Azimuth(struct site source, struct site destination);
|
||||
double ElevationAngle(struct site source, struct site destination);
|
||||
void ReadPath(struct site source, struct site destination);
|
||||
double ElevationAngle2(struct site source, struct site destination, double er);
|
||||
double ReadBearing(char *input);
|
||||
void ObstructionAnalysis(struct site xmtr, struct site rcvr, double f, FILE *outfile);
|
||||
void free_elev(void);
|
||||
void free_path(void);
|
||||
void free_dem(void);
|
||||
void alloc_elev(void);
|
||||
void alloc_path(void);
|
||||
void alloc_dem(void);
|
||||
void do_allocs(void);
|
||||
|
||||
#endif /* _MAIN_HH_ */
|
9
src/models/README
Normal file
9
src/models/README
Normal file
@@ -0,0 +1,9 @@
|
||||
Whilst every effort has been made to ensure the accuracy of the models, their
|
||||
accuracy is not guaranteed.
|
||||
|
||||
Finding a reputable paper to source these models from took a while. There was
|
||||
lots of bad copy-paste out there. A good paper:
|
||||
|
||||
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
|
||||
Plane earth loss model taken from "Antennas and Propagation for Wireless systems" by Simon Saunders
|
61
src/models/cost.cc
Normal file
61
src/models/cost.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
/*****************************************************************************
|
||||
* COST231-HATA MODEL for Signal Server by Alex Farrant *
|
||||
* 30 December 2013i *
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
/*
|
||||
COST231 extension to HATA model
|
||||
Frequency 1500 to 2000MHz
|
||||
TxH = Base station height 30 to 200m
|
||||
RxH = Mobile station height 1 to 10m
|
||||
Distance 1-20km
|
||||
modes 1 = URBAN, 2 = SUBURBAN, 3 = OPEN
|
||||
http://morse.colorado.edu/~tlen5510/text/classwebch3.html
|
||||
*/
|
||||
/* if (f < 150 || f > 2000) {
|
||||
fprintf
|
||||
(stderr,"Error: COST231 Hata model frequency range 150-2000MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*/
|
||||
int C = 3; // 3dB for Urban
|
||||
float lRxH = log10(11.75 * RxH);
|
||||
float C_H = 3.2 * (lRxH * lRxH) - 4.97; // Large city (conservative)
|
||||
int c0 = 69.55;
|
||||
int cf = 26.16;
|
||||
if (f > 1500) {
|
||||
c0 = 46.3;
|
||||
cf = 33.9;
|
||||
}
|
||||
if (mode == 2) {
|
||||
C = 0; // Medium city (average)
|
||||
lRxH = log10(1.54 * RxH);
|
||||
C_H = 8.29 * (lRxH * lRxH) - 1.1;
|
||||
}
|
||||
if (mode == 3) {
|
||||
C = -3; // Small city (Optimistic)
|
||||
C_H = (1.1 * log10(f) - 0.7) * RxH - (1.56 * log10(f)) + 0.8;
|
||||
}
|
||||
float logf = log10(f);
|
||||
double dbloss =
|
||||
c0 + (cf * logf) - (13.82 * log10(TxH)) - C_H + (44.9 -
|
||||
6.55 *
|
||||
log10(TxH)) *
|
||||
log10(d) + C;
|
||||
return dbloss;
|
||||
}
|
6
src/models/cost.hh
Normal file
6
src/models/cost.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _COST_HH_
|
||||
#define _COST_HH_
|
||||
|
||||
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _COST_HH_ */
|
33
src/models/ecc33.cc
Normal file
33
src/models/ecc33.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
|
||||
// Sanity check as this model operates within limited Txh/Rxh bounds
|
||||
if(TxH-RxH<0){
|
||||
RxH=RxH/(d*2);
|
||||
}
|
||||
|
||||
/* if (f < 700 || f > 3500) {
|
||||
fprintf(stderr,"Error: ECC33 model frequency range 700-3500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*/
|
||||
// MHz to GHz
|
||||
f = f / 1000;
|
||||
|
||||
double Gr = 0.759 * RxH - 1.862; // Big city with tall buildings (1)
|
||||
// PL = Afs + Abm - Gb - Gr
|
||||
double Afs = 92.4 + 20 * log10(d) + 20 * log10(f);
|
||||
double Abm =
|
||||
20.41 + 9.83 * log10(d) + 7.894 * log10(f) +
|
||||
9.56 * (log10(f) * log10(f));
|
||||
double Gb = log10(TxH / 200) * (13.958 + 5.8 * (log10(d) * log10(d)));
|
||||
if (mode > 1) { // Medium city (Europe)
|
||||
Gr = (42.57 + 13.7 * log10(f)) * (log10(RxH) - 0.585);
|
||||
}
|
||||
|
||||
return Afs + Abm - Gb - Gr;
|
||||
}
|
6
src/models/ecc33.hh
Normal file
6
src/models/ecc33.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ECC33_HH_
|
||||
#define _ECC33_HH_
|
||||
|
||||
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _ECC33_HH_ */
|
83
src/models/egli.cc
Normal file
83
src/models/egli.cc
Normal file
@@ -0,0 +1,83 @@
|
||||
/*****************************************************************************
|
||||
* Egli VHF/UHF model for Signal Server by G6DTX *
|
||||
* April 2017 *
|
||||
* 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 v3 *
|
||||
* for more details. *
|
||||
******************************************************************************
|
||||
|
||||
Frequency 30 to 1000MHz
|
||||
h1 = 1m and above
|
||||
h2 = 1m and above
|
||||
Distance 1 to 50km
|
||||
|
||||
http://people.seas.harvard.edu/~jones/es151/prop_models/propagation.html#pel
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
//static float fcmin = 30.0;
|
||||
//static float fcmax = 1000.0;
|
||||
//static float dmin = 1.0;
|
||||
//static float dmax = 50.0;
|
||||
//static float h1min = 1.0;
|
||||
//static float h2min = 1.0;
|
||||
|
||||
static __inline float _10log10f(float x)
|
||||
{
|
||||
return(4.342944f*logf(x));
|
||||
}
|
||||
|
||||
double EgliPathLoss(float f, float h1, float h2, float d)
|
||||
{
|
||||
double Lp50 = NAN;
|
||||
float C1, C2;
|
||||
|
||||
/* if ((f >= fcmin) && (f <= fcmax) &&
|
||||
(h1 >= h1min) && (h2 >= h2min))
|
||||
{*/
|
||||
if (h1 > 10.0 && h2 > 10.0)
|
||||
{
|
||||
Lp50 = 85.9;
|
||||
C1 = 2.0;
|
||||
C2 = 2.0;
|
||||
}
|
||||
else if (h1 > 10.0)
|
||||
{
|
||||
Lp50 = 76.3;
|
||||
C1 = 2.0;
|
||||
C2 = 1.0;
|
||||
}
|
||||
else if (h2 > 10.0)
|
||||
{
|
||||
Lp50 = 76.3;
|
||||
C1 = 1.0;
|
||||
C2 = 2.0;
|
||||
}
|
||||
else // both antenna heights below 10 metres
|
||||
{
|
||||
Lp50 = 66.7;
|
||||
C1 = 1.0;
|
||||
C2 = 1.0;
|
||||
} // end if
|
||||
|
||||
Lp50 += 4.0f*_10log10f(d) + 2.0f*_10log10f(f) - C1*_10log10f(h1) - C2*_10log10f(h2);
|
||||
/*}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Parameter error: Egli path loss model f=%6.2f h1=%6.2f h2=%6.2f d=%6.2f\n", f, h1, h2, d);
|
||||
exit(EXIT_FAILURE);
|
||||
}*/
|
||||
|
||||
return(Lp50);
|
||||
|
||||
}
|
||||
|
6
src/models/egli.hh
Normal file
6
src/models/egli.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _EGLI_HH_
|
||||
#define _EGLI_HH_
|
||||
|
||||
double EgliPathLoss(float f, float h1, float h2, float d);
|
||||
|
||||
#endif /* _EGLI_HH_ */
|
31
src/models/ericsson.cc
Normal file
31
src/models/ericsson.cc
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
/*
|
||||
AKA Ericsson 9999 model
|
||||
*/
|
||||
// Urban
|
||||
double a0 = 36.2, a1 = 30.2, a2 = -12, a3 = 0.1;
|
||||
|
||||
/* if (f < 150 || f > 1900) {
|
||||
fprintf
|
||||
(stderr,"Error: Ericsson9999 model frequency range 150-1900MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*/
|
||||
if (mode == 2) { // Suburban / Med loss
|
||||
a0 = 43.2;
|
||||
a1 = 68.93;
|
||||
}
|
||||
if (mode == 1) { // Rural
|
||||
a0 = 45.95;
|
||||
a1 = 100.6;
|
||||
}
|
||||
double g1 = 3.2 * (log10(11.75 * RxH) * log10(11.75 * RxH));
|
||||
double g2 = 44.49 * log10(f) - 4.78 * (log10(f) * log10(f));
|
||||
|
||||
return a0 + a1 * log10(d) + a2 * log10(TxH) + a3 * log10(TxH) * log10(d) - g1 + g2;
|
||||
}
|
6
src/models/ericsson.hh
Normal file
6
src/models/ericsson.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ERICSSON_HH_
|
||||
#define _ERICSSON_HH_
|
||||
|
||||
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _ERICSSON_HH_ */
|
33
src/models/fspl.cc
Normal file
33
src/models/fspl.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
/*****************************************************************************
|
||||
* ITU-R P.525 Free Space Path Loss model for Signal Server by Alex Farrant *
|
||||
* 15 January 2014 *
|
||||
* optimised G6DTX April 2017 *
|
||||
* 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. *
|
||||
*
|
||||
* https://www.itu.int/rec/R-REC-P.525/en
|
||||
* Free Space Path Loss model
|
||||
* Frequency: Any
|
||||
* Distance: Any
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// use call with log/ln as this may be faster
|
||||
// use constant of value 20.0/log(10.0)
|
||||
static __inline float _20log10f(float x)
|
||||
{
|
||||
return(8.685889f*logf(x));
|
||||
}
|
||||
|
||||
double FSPLpathLoss(float f, float d)
|
||||
{
|
||||
return(32.44 + _20log10f(f) + _20log10f(d));
|
||||
}
|
6
src/models/fspl.hh
Normal file
6
src/models/fspl.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _FSPL_HH_
|
||||
#define _FSPL_HH_
|
||||
|
||||
double FSPLpathLoss(float f, float d);
|
||||
|
||||
#endif /* _FSPL_HH_ */
|
58
src/models/hata.cc
Normal file
58
src/models/hata.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
/*****************************************************************************
|
||||
* 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 <math.h>
|
||||
|
||||
double HATApathLoss(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;
|
||||
float C_H;
|
||||
float logf = log10(f);
|
||||
|
||||
if(f<200){
|
||||
lh_M = log10(1.54 * h_M);
|
||||
C_H = 8.29 * (lh_M * lh_M) - 1.1;
|
||||
}else{
|
||||
lh_M = log10(11.75 * h_M);
|
||||
C_H = 3.2 * (lh_M * lh_M) - 4.97;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
6
src/models/hata.hh
Normal file
6
src/models/hata.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _HATA_HH_
|
||||
#define _HATA_HH_
|
||||
|
||||
double HATApathLoss(float f, float h_B, float h_M, float d, int mode);
|
||||
|
||||
#endif /* _HATA_HH_ */
|
1574
src/models/itm.cc
Normal file
1574
src/models/itm.cc
Normal file
File diff suppressed because it is too large
Load Diff
2964
src/models/itwom3.0.cc
Normal file
2964
src/models/itwom3.0.cc
Normal file
File diff suppressed because it is too large
Load Diff
14
src/models/itwom3.0.hh
Normal file
14
src/models/itwom3.0.hh
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _ITWOM30_HH_
|
||||
#define _ITWOM30_HH_
|
||||
|
||||
void point_to_point_ITM(double tht_m, double rht_m, double eps_dielect,
|
||||
double sgm_conductivity, double eno_ns_surfref,
|
||||
double frq_mhz, int radio_climate, int pol,
|
||||
double conf, double rel, double &dbloss, char *strmode,
|
||||
int &errnum);
|
||||
void point_to_point(double tht_m, double rht_m, double eps_dielect,
|
||||
double sgm_conductivity, double eno_ns_surfref,
|
||||
double frq_mhz, int radio_climate, int pol, double conf,
|
||||
double rel, double &dbloss, char *strmode, int &errnum);
|
||||
|
||||
#endif /* _ITWOM30_HH_ */
|
948
src/models/los.cc
Normal file
948
src/models/los.cc
Normal file
@@ -0,0 +1,948 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "../main.hh"
|
||||
#include "los.hh"
|
||||
#include "cost.hh"
|
||||
#include "ecc33.hh"
|
||||
#include "ericsson.hh"
|
||||
#include "fspl.hh"
|
||||
#include "hata.hh"
|
||||
#include "itwom3.0.hh"
|
||||
#include "sui.hh"
|
||||
#include "pel.hh"
|
||||
#include "egli.hh"
|
||||
#include "soil.hh"
|
||||
#include <pthread.h>
|
||||
|
||||
#define NUM_SECTIONS 4
|
||||
|
||||
namespace {
|
||||
pthread_t threads[NUM_SECTIONS];
|
||||
unsigned int thread_count = 0;
|
||||
pthread_mutex_t maskMutex;
|
||||
bool ***processed;
|
||||
bool has_init_processed = false;
|
||||
|
||||
struct propagationRange {
|
||||
double 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()
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
processed = new bool **[MAXPAGES];
|
||||
for (i = 0; i < MAXPAGES; i++) {
|
||||
processed[i] = new bool *[ippd];
|
||||
for (x = 0; x < ippd; x++)
|
||||
processed[i][x] = new bool [ippd];
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPAGES; i++) {
|
||||
for (x = 0; x < ippd; x++) {
|
||||
for (y = 0; y < ippd; y++)
|
||||
processed[i][x][y] = false;
|
||||
}
|
||||
}
|
||||
|
||||
has_init_processed = true;
|
||||
}
|
||||
|
||||
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(yppd * (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)
|
||||
fprintf(stderr,"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)
|
||||
fprintf(stderr,"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
|
||||
* distance (adj)
|
||||
*/
|
||||
static double incidenceAngle(double opp, double adj)
|
||||
{
|
||||
return atan2(opp, adj) * 180 / PI;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knife edge diffraction:
|
||||
* This is based upon a recognised formula like Huygens, but trades
|
||||
* thoroughness for increased speed which adds a proportional diffraction
|
||||
* effect to obstacles.
|
||||
*/
|
||||
static double ked(double freq, double rxh, double dkm)
|
||||
{
|
||||
double obh, obd, rxobaoi = 0, d;
|
||||
|
||||
obh = 0; // Obstacle height
|
||||
obd = 0; // Obstacle distance
|
||||
|
||||
dkm = dkm * 1000; // KM to metres
|
||||
|
||||
// walk along path
|
||||
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] < obh) {
|
||||
|
||||
// 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 / (300 / freq))+3; // Diffraction angle divided by wavelength (m)
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||
FILE *fd)
|
||||
{
|
||||
/* This function analyzes the path between the source and
|
||||
destination locations. It determines which points along
|
||||
the path have line-of-sight visibility to the source.
|
||||
Points along with path having line-of-sight visibility
|
||||
to the source at an AGL altitude equal to that of the
|
||||
destination location are stored by setting bit 1 in the
|
||||
mask[][] array, which are displayed in green when PPM
|
||||
maps are later generated by ss. */
|
||||
|
||||
char block;
|
||||
int x, y;
|
||||
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||
double distance, rx_alt, tx_alt;
|
||||
|
||||
ReadPath(source, destination);
|
||||
for (y = 0; (y < (path.length - 1) && path.distance[y] <= max_range);
|
||||
y++) {
|
||||
//for (y = 0; y < path.length; y++) {
|
||||
/* 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
|
||||
&& can_process(path.lat[y], path.lon[y])) {
|
||||
|
||||
distance = FEET_PER_MILE * path.distance[y];
|
||||
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||
rx_alt =
|
||||
earthradius + destination.alt + path.elevation[y];
|
||||
|
||||
/* Calculate the cosine of the elevation of the
|
||||
transmitter as seen at the temp rx point. */
|
||||
|
||||
cos_xmtr_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||
|
||||
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||
distance =
|
||||
FEET_PER_MILE * (path.distance[y] -
|
||||
path.distance[x]);
|
||||
test_alt =
|
||||
earthradius + (path.elevation[x] ==
|
||||
0.0 ? path.
|
||||
elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
cos_test_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||
distance);
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the following "if"
|
||||
statement is reversed from what it would
|
||||
be if the actual angles were compared. */
|
||||
|
||||
if (cos_xmtr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block == 0)
|
||||
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlotPropPath(struct site source, struct site destination,
|
||||
unsigned char mask_value, FILE * fd, int propmodel,
|
||||
int knifeedge, int pmenv)
|
||||
{
|
||||
|
||||
int x, y, ifs, ofs, errnum;
|
||||
char block = 0, strmode[100];
|
||||
double loss, azimuth, pattern = 0.0,
|
||||
xmtr_alt, dest_alt, xmtr_alt2, dest_alt2,
|
||||
cos_rcvr_angle, cos_test_angle = 0.0, test_alt,
|
||||
elevation = 0.0, distance = 0.0, four_thirds_earth,
|
||||
field_strength = 0.0, rxp, dBm, diffloss;
|
||||
struct site temp;
|
||||
float dkm;
|
||||
|
||||
ReadPath(source, destination);
|
||||
|
||||
four_thirds_earth = FOUR_THIRDS * EARTHRADIUS;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* Copy ending points without clutter */
|
||||
|
||||
elev[2] = path.elevation[0] * METERS_PER_FOOT;
|
||||
|
||||
elev[path.length + 1] =
|
||||
path.elevation[path.length - 1] * METERS_PER_FOOT;
|
||||
|
||||
/* Since the only energy the Longley-Rice model considers
|
||||
reaching the destination is based on what is scattered
|
||||
or deflected from the first obstruction along the path,
|
||||
we first need to find the location and elevation angle
|
||||
of that first obstruction (if it exists). This is done
|
||||
using a 4/3rds Earth radius to match the model used by
|
||||
Longley-Rice. This information is required for properly
|
||||
integrating the antenna's elevation pattern into the
|
||||
calculation for overall path loss. */
|
||||
//if(debug)
|
||||
// fprintf(stderr,"four_thirds_earth %.1f source.alt %.1f path.elevation[0] %.1f\n",four_thirds_earth,source.alt,path.elevation[0]);
|
||||
for (y = 2; (y < (path.length - 1) && path.distance[y] <= max_range);
|
||||
y++) {
|
||||
/* Process this point only if it
|
||||
has not already been processed. */
|
||||
|
||||
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 = FEET_PER_MILE * path.distance[y];
|
||||
xmtr_alt =
|
||||
four_thirds_earth + source.alt + path.elevation[0];
|
||||
dest_alt =
|
||||
four_thirds_earth + destination.alt +
|
||||
path.elevation[y];
|
||||
dest_alt2 = dest_alt * dest_alt;
|
||||
xmtr_alt2 = xmtr_alt * xmtr_alt;
|
||||
|
||||
/* Calculate the cosine of the elevation of
|
||||
the receiver as seen by the transmitter. */
|
||||
|
||||
cos_rcvr_angle =
|
||||
((xmtr_alt2) + (distance * distance) -
|
||||
(dest_alt2)) / (2.0 * xmtr_alt * distance);
|
||||
|
||||
if (cos_rcvr_angle > 1.0)
|
||||
cos_rcvr_angle = 1.0;
|
||||
|
||||
if (cos_rcvr_angle < -1.0)
|
||||
cos_rcvr_angle = -1.0;
|
||||
|
||||
if (got_elevation_pattern || fd != NULL) {
|
||||
/* Determine the elevation angle to the first obstruction
|
||||
along the path IF elevation pattern data is available
|
||||
or an output (.ano) file has been designated. */
|
||||
|
||||
for (x = 2, block = 0; (x < y && block == 0);
|
||||
x++) {
|
||||
distance = FEET_PER_MILE * path.distance[x];
|
||||
|
||||
test_alt =
|
||||
four_thirds_earth +
|
||||
(path.elevation[x] ==
|
||||
0.0 ? path.elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
/* Calculate the cosine of the elevation
|
||||
angle of the terrain (test point)
|
||||
as seen by the transmitter. */
|
||||
|
||||
cos_test_angle =
|
||||
((xmtr_alt2) +
|
||||
(distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 *
|
||||
xmtr_alt
|
||||
*
|
||||
distance);
|
||||
|
||||
if (cos_test_angle > 1.0)
|
||||
cos_test_angle = 1.0;
|
||||
|
||||
if (cos_test_angle < -1.0)
|
||||
cos_test_angle = -1.0;
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the sense of the
|
||||
following "if" statement is reversed from
|
||||
what it would be if the angles themselves
|
||||
were compared. */
|
||||
|
||||
if (cos_rcvr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block)
|
||||
elevation =
|
||||
((acos(cos_test_angle)) / DEG2RAD) -
|
||||
90.0;
|
||||
else
|
||||
elevation =
|
||||
((acos(cos_rcvr_angle)) / DEG2RAD) -
|
||||
90.0;
|
||||
}
|
||||
|
||||
/* Determine attenuation for each point along the
|
||||
path using a prop model starting at y=2 (number_of_points = 1), the
|
||||
shortest distance terrain can play a role in
|
||||
path loss. */
|
||||
|
||||
elev[0] = y - 1; /* (number of points - 1) */
|
||||
|
||||
/* Distance between elevation samples */
|
||||
|
||||
elev[1] =
|
||||
METERS_PER_MILE * (path.distance[y] -
|
||||
path.distance[y - 1]);
|
||||
|
||||
if (path.elevation[y] < 1) {
|
||||
path.elevation[y] = 1;
|
||||
}
|
||||
|
||||
dkm = (elev[1] * elev[0]) / 1000; // km
|
||||
|
||||
switch (propmodel) {
|
||||
case 1:
|
||||
// Longley Rice ITM
|
||||
point_to_point_ITM(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 1, 2 & 3
|
||||
loss =
|
||||
HATApathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||
(path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 4:
|
||||
// ECC33
|
||||
loss =
|
||||
ECC33pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||
(path.elevation[y] *
|
||||
METERS_PER_FOOT) +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
case 5:
|
||||
// SUI
|
||||
loss =
|
||||
SUIpathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||
(path.elevation[y] *
|
||||
METERS_PER_FOOT) +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 6:
|
||||
// COST231-Hata
|
||||
loss =
|
||||
COST231pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||
(path.elevation[y] *
|
||||
METERS_PER_FOOT) +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
case 7:
|
||||
// ITU-R P.525 Free space path loss
|
||||
loss = FSPLpathLoss(LR.frq_mhz, dkm);
|
||||
break;
|
||||
case 8:
|
||||
// ITWOM 3.0
|
||||
point_to_point(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 9:
|
||||
// Ericsson
|
||||
loss =
|
||||
EricssonpathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||
(path.elevation[y] *
|
||||
METERS_PER_FOOT) +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
case 10:
|
||||
// Plane earth
|
||||
loss = PlaneEarthLoss(dkm, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT));
|
||||
break;
|
||||
case 11:
|
||||
// Egli VHF/UHF
|
||||
loss = EgliPathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT),dkm);
|
||||
break;
|
||||
case 12:
|
||||
// Soil
|
||||
loss = SoilPathLoss(LR.frq_mhz, dkm, LR.eps_dielect);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
point_to_point_ITM(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 && propmodel > 1) {
|
||||
diffloss =
|
||||
ked(LR.frq_mhz,
|
||||
destination.alt * METERS_PER_FOOT, dkm);
|
||||
loss += (diffloss); // ;)
|
||||
}
|
||||
//Key stage. Link dB for p2p is returned as 'loss'.
|
||||
|
||||
temp.lat = path.lat[y];
|
||||
temp.lon = path.lon[y];
|
||||
|
||||
azimuth = (Azimuth(source, temp));
|
||||
|
||||
if (fd != NULL)
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.7f, %.7f, %.3f, %.3f, ",
|
||||
path.lat[y], path.lon[y], azimuth,
|
||||
elevation);
|
||||
|
||||
/* If ERP==0, write path loss to alphanumeric
|
||||
output file. Otherwise, write field strength
|
||||
or received power level (below), as appropriate. */
|
||||
|
||||
if (fd != NULL && LR.erp == 0.0)
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.2f", loss);
|
||||
|
||||
/* Integrate the antenna's radiation
|
||||
pattern into the overall path loss. */
|
||||
|
||||
x = (int)rint(10.0 * (10.0 - elevation));
|
||||
|
||||
if (x >= 0 && x <= 1000) {
|
||||
azimuth = rint(azimuth);
|
||||
|
||||
pattern =
|
||||
(double)LR.antenna_pattern[(int)azimuth][x];
|
||||
|
||||
if (pattern != 0.0) {
|
||||
pattern = 20.0 * log10(pattern);
|
||||
loss -= pattern;
|
||||
}
|
||||
}
|
||||
|
||||
if (LR.erp != 0.0) {
|
||||
if (dbm) {
|
||||
/* dBm is based on EIRP (ERP + 2.14) */
|
||||
|
||||
rxp =
|
||||
LR.erp /
|
||||
(pow(10.0, (loss - 2.14) / 10.0));
|
||||
|
||||
dBm = 10.0 * (log10(rxp * 1000.0));
|
||||
|
||||
if (fd != NULL)
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.3f", dBm);
|
||||
|
||||
/* Scale roughly between 0 and 255 */
|
||||
|
||||
ifs = 200 + (int)rint(dBm);
|
||||
|
||||
if (ifs < 0)
|
||||
ifs = 0;
|
||||
|
||||
if (ifs > 255)
|
||||
ifs = 255;
|
||||
|
||||
ofs =
|
||||
GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs > ifs)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
field_strength =
|
||||
(139.4 +
|
||||
(20.0 * log10(LR.frq_mhz)) -
|
||||
loss) +
|
||||
(10.0 * log10(LR.erp / 1000.0));
|
||||
|
||||
ifs = 100 + (int)rint(field_strength);
|
||||
|
||||
if (ifs < 0)
|
||||
ifs = 0;
|
||||
|
||||
if (ifs > 255)
|
||||
ifs = 255;
|
||||
|
||||
ofs =
|
||||
GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs > ifs)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
|
||||
if (fd != NULL)
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
"%.3f",
|
||||
field_strength);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (loss > 255)
|
||||
ifs = 255;
|
||||
else
|
||||
ifs = (int)rint(loss);
|
||||
|
||||
ofs = GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs < ifs && ofs != 0)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
}
|
||||
|
||||
if (fd != NULL) {
|
||||
if (block)
|
||||
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||
" *");
|
||||
fprintf(fd, "%s\n", fd_buffer);
|
||||
}
|
||||
|
||||
/* Mark this point as having been analyzed */
|
||||
|
||||
PutMask(path.lat[y], path.lon[y],
|
||||
(GetMask(path.lat[y], path.lon[y]) & 7) +
|
||||
(mask_value << 3));
|
||||
}
|
||||
}
|
||||
|
||||
if(path.lat[y]>cropLat)
|
||||
cropLat=path.lat[y];
|
||||
|
||||
|
||||
if(y>cropLon)
|
||||
cropLon=y;
|
||||
|
||||
//if(cropLon>180)
|
||||
// cropLon-=360;
|
||||
}
|
||||
|
||||
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
|
||||
line-of-sight coverage of the transmitter 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 WritePPM() function
|
||||
is later invoked. */
|
||||
|
||||
static __thread unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
if (plo_filename[0] != 0)
|
||||
fd = fopen(plo_filename, "wb");
|
||||
|
||||
if (fd != NULL) {
|
||||
fprintf(fd,
|
||||
"%.3f, %.3f\t; max_west, min_west\n%.3f, %.3f\t; max_north, min_north\n",
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
// Four sections start here
|
||||
// Process north edge east/west, east edge north/south,
|
||||
// south edge east/west, west edge north/south
|
||||
double range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||
double range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||
double range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||
double range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||
propagationRange* r[NUM_SECTIONS];
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||
propagationRange *range = new propagationRange;
|
||||
r[i] = range;
|
||||
range->los = true;
|
||||
|
||||
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];
|
||||
|
||||
range->use_threads = use_threads;
|
||||
range->altitude = altitude;
|
||||
range->source = source;
|
||||
range->mask_value = mask_value;
|
||||
range->fd = fd;
|
||||
|
||||
if(use_threads)
|
||||
beginThread(range);
|
||||
else
|
||||
rangePropagation(range);
|
||||
|
||||
}
|
||||
|
||||
if(use_threads)
|
||||
finishThreads();
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||
delete r[i];
|
||||
}
|
||||
|
||||
switch (mask_value) {
|
||||
case 1:
|
||||
mask_value = 8;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
mask_value = 16;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
mask_value = 32;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
int propmodel, int knifeedge, int haf, int pmenv, bool
|
||||
use_threads)
|
||||
{
|
||||
static __thread unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
if (LR.erp == 0.0 && debug)
|
||||
fprintf(stderr, "path loss");
|
||||
else {
|
||||
if (debug) {
|
||||
if (dbm)
|
||||
fprintf(stderr, "signal power level");
|
||||
else
|
||||
fprintf(stderr, "field strength");
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
fprintf(stderr,
|
||||
" contours of \"%s\" out to a radius of %.2f %s with Rx antenna(s) at %.2f %s AGL\n",
|
||||
source.name,
|
||||
metric ? max_range * KM_PER_MILE : max_range,
|
||||
metric ? "kilometers" : "miles",
|
||||
metric ? altitude * METERS_PER_FOOT : altitude,
|
||||
metric ? "meters" : "feet");
|
||||
}
|
||||
|
||||
if (clutter > 0.0 && debug)
|
||||
fprintf(stderr, "\nand %.2f %s of ground clutter",
|
||||
metric ? clutter * METERS_PER_FOOT : clutter,
|
||||
metric ? "meters" : "feet");
|
||||
|
||||
if (plo_filename[0] != 0)
|
||||
fd = fopen(plo_filename, "wb");
|
||||
|
||||
if (fd != NULL) {
|
||||
fprintf(fd,
|
||||
"%.3f, %.3f\t; max_west, min_west\n%.3f, %.3f\t; max_north, min_north\n",
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
|
||||
// Four sections start here
|
||||
// Process north edge east/west, east edge north/south,
|
||||
// south edge east/west, west edge north/south
|
||||
double range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||
double range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||
double range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||
double range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||
propagationRange* r[NUM_SECTIONS];
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||
propagationRange *range = new propagationRange;
|
||||
r[i] = range;
|
||||
range->los = false;
|
||||
|
||||
// Only process correct half
|
||||
if((NUM_SECTIONS - i) <= (NUM_SECTIONS / 2) && haf == 1)
|
||||
continue;
|
||||
if((NUM_SECTIONS - i) > (NUM_SECTIONS / 2) && haf == 2)
|
||||
continue;
|
||||
|
||||
|
||||
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];
|
||||
|
||||
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(use_threads)
|
||||
beginThread(range);
|
||||
else
|
||||
rangePropagation(range);
|
||||
|
||||
}
|
||||
|
||||
if(use_threads)
|
||||
finishThreads();
|
||||
|
||||
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||
delete r[i];
|
||||
}
|
||||
|
||||
if (fd != NULL)
|
||||
fclose(fd);
|
||||
|
||||
if (mask_value < 30)
|
||||
mask_value++;
|
||||
}
|
||||
|
||||
void PlotPath(struct site source, struct site destination, char mask_value)
|
||||
{
|
||||
/* This function analyzes the path between the source and
|
||||
destination locations. It determines which points along
|
||||
the path have line-of-sight visibility to the source.
|
||||
Points along with path having line-of-sight visibility
|
||||
to the source at an AGL altitude equal to that of the
|
||||
destination location are stored by setting bit 1 in the
|
||||
mask[][] array, which are displayed in green when PPM
|
||||
maps are later generated by SPLAT!. */
|
||||
|
||||
char block;
|
||||
int x, y;
|
||||
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||
double distance, rx_alt, tx_alt;
|
||||
|
||||
ReadPath(source, destination);
|
||||
|
||||
for (y = 0; y < path.length; y++) {
|
||||
/* 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) {
|
||||
distance = FEET_PER_MILE * path.distance[y];
|
||||
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||
rx_alt =
|
||||
earthradius + destination.alt + path.elevation[y];
|
||||
|
||||
/* Calculate the cosine of the elevation of the
|
||||
transmitter as seen at the temp rx point. */
|
||||
|
||||
cos_xmtr_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||
|
||||
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||
distance =
|
||||
FEET_PER_MILE * (path.distance[y] -
|
||||
path.distance[x]);
|
||||
test_alt =
|
||||
earthradius + (path.elevation[x] ==
|
||||
0.0 ? path.
|
||||
elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
cos_test_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||
distance);
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the following "if"
|
||||
statement is reversed from what it would
|
||||
be if the actual angles were compared. */
|
||||
|
||||
if (cos_xmtr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block == 0)
|
||||
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||
}
|
||||
}
|
||||
}
|
18
src/models/los.hh
Normal file
18
src/models/los.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _LOS_HH_
|
||||
#define _LOS_HH_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||
FILE *fd);
|
||||
void PlotPropPath(struct site source, struct site destination,
|
||||
unsigned char mask_value, FILE * fd, int propmodel,
|
||||
int knifeedge, int pmenv);
|
||||
void PlotLOSMap(struct site source, double altitude, char *plo_filename, bool use_threads);
|
||||
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
int propmodel, int knifeedge, int haf, int pmenv, bool use_threads);
|
||||
void PlotPath(struct site source, struct site destination, char mask_value);
|
||||
|
||||
#endif /* _LOS_HH_ */
|
29
src/models/pel.cc
Normal file
29
src/models/pel.cc
Normal file
@@ -0,0 +1,29 @@
|
||||
/*****************************************************************************
|
||||
* Plane Earth Path Loss model for Signal Server by Alex Farrant *
|
||||
* Taken from "Antennas and Propagation for wireless communication systems" *
|
||||
* ISBN 978-0-470-84879-1 *
|
||||
* 10 August 2016 *
|
||||
* 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 <math.h>
|
||||
|
||||
double PlaneEarthLoss(float d, float TxH, float RxH)
|
||||
{
|
||||
/*
|
||||
Plane Earth Loss model
|
||||
Frequency: N/A
|
||||
Distance (km): Any
|
||||
*/
|
||||
// Plane earth loss is independent of frequency.
|
||||
double dbloss = 40*log10(d) + 20*log10(TxH) + 20*log10(RxH);
|
||||
return dbloss;
|
||||
}
|
6
src/models/pel.hh
Normal file
6
src/models/pel.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _PEL_HH_
|
||||
#define _PEL_HH_
|
||||
|
||||
double PlaneEarthLoss(float d, float TxH, float RxH);
|
||||
|
||||
#endif /* _PEL_HH_ */
|
33
src/models/soil.cc
Normal file
33
src/models/soil.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
/*****************************************************************************
|
||||
* Soil Path Loss model for Signal Server by Alex Farrant *
|
||||
* 21 February 2018 *
|
||||
* *
|
||||
* 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. *
|
||||
*
|
||||
* Frequency: Any MHz
|
||||
* Distance: Any Km
|
||||
* Terrain permittivity: 1 - 15 (Bad to Good)
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// use call with log/ln as this may be faster
|
||||
// use constant of value 20.0/log(10.0)
|
||||
static __inline float _20log10f(float x)
|
||||
{
|
||||
return(8.685889f*logf(x));
|
||||
}
|
||||
|
||||
double SoilPathLoss(float f, float d, float terdic)
|
||||
{
|
||||
float soil = (120/terdic);
|
||||
return(6.4 + _20log10f(d) + _20log10f(f)+(8.69*soil));
|
||||
}
|
6
src/models/soil.hh
Normal file
6
src/models/soil.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _SOIL_HH_
|
||||
#define _SOIL_HH_
|
||||
|
||||
double SoilPathLoss(float f, float d, float t);
|
||||
|
||||
#endif /* _SOIL_HH_ */
|
65
src/models/sui.cc
Normal file
65
src/models/sui.cc
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// use call with log/ln as this may be faster
|
||||
// use constant of value 20.0/log(10.0)
|
||||
static __inline float _20log10f(float x)
|
||||
{
|
||||
return(8.685889f*logf(x));
|
||||
}
|
||||
|
||||
|
||||
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode)
|
||||
{
|
||||
/*
|
||||
f = Frequency (MHz) 1900 to 11000
|
||||
TxH = Transmitter height (m)
|
||||
RxH = Receiver height (m)
|
||||
d = distance (km)
|
||||
mode A1 = URBAN / OBSTRUCTED
|
||||
mode B2 = SUBURBAN / PARTIALLY OBSTRUCTED
|
||||
mode C3 = RURAL / OPEN
|
||||
Paper 1 has a Rx height correction of / 2000
|
||||
Paper 2 has the same correction as / 2 and gives better results
|
||||
"Ranked number 2 University in the wurld"
|
||||
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
https://mentor.ieee.org/802.19/file/08/19-08-0010-00-0000-sui-path-loss-model.doc
|
||||
*/
|
||||
d *= 1e3; // km to m
|
||||
|
||||
// Urban (A1) is default
|
||||
float a = 4.6;
|
||||
float b = 0.0075;
|
||||
float c = 12.6;
|
||||
float s = 8.2; // Optional fading value. 8.2 to 10.6dB
|
||||
float XhCF = -10.8;
|
||||
|
||||
if (mode == 2) { // Suburban
|
||||
a = 4.0;
|
||||
b = 0.0065;
|
||||
c = 17.1;
|
||||
XhCF = -10.8;
|
||||
}
|
||||
if (mode == 3) { // Rural
|
||||
a = 3.6;
|
||||
b = 0.005;
|
||||
c = 20;
|
||||
XhCF = -20;
|
||||
}
|
||||
float d0 = 100.0;
|
||||
float A = _20log10f((4 * M_PI * d0) / (300.0 / f));
|
||||
float y = a - (b * TxH) + (c / TxH);
|
||||
|
||||
// Assume 2.4GHz
|
||||
float Xf = 0;
|
||||
float Xh = 0;
|
||||
|
||||
//Correction factors for > 2GHz
|
||||
if(f>2000){
|
||||
Xf=6.0 * log10(f / 2.0);
|
||||
Xh=XhCF * log10(RxH / 2.0);
|
||||
}
|
||||
return A + (10 * y) * (log10(d / d0)) + Xf + Xh + s;
|
||||
}
|
6
src/models/sui.hh
Normal file
6
src/models/sui.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _SUI_HH_
|
||||
#define _SUI_HH_
|
||||
|
||||
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
|
||||
|
||||
#endif /* _SUI_HH_ */
|
118
src/models/testmodels.cc
Normal file
118
src/models/testmodels.cc
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
/*
|
||||
* Propagation model test script for signal server
|
||||
* Requires gnuplot
|
||||
* Compile: gcc -Wall -o test test.cc sui.cc cost.cc ecc33.cc ericsson.cc fspl.cc egli.cc hata.cc -lm
|
||||
* Test 850Mhz: ./test 850
|
||||
*
|
||||
* 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. *
|
||||
* *
|
||||
\****************************************************************************/
|
||||
|
||||
|
||||
extern double EgliPathLoss(float f, float TxH, float RxH, float d);
|
||||
extern double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
|
||||
extern double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
extern double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
extern double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
extern double FSPLpathLoss(float f, float d);
|
||||
extern double HATApathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
extern void point_to_point_ITM(double tht_m, double rht_m, double eps_dielect,
|
||||
double sgm_conductivity, double eno_ns_surfref,
|
||||
double frq_mhz, int radio_climate, int pol,
|
||||
double conf, double rel, double &dbloss, char *strmode,
|
||||
int &errnum);
|
||||
__thread double *elev;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
double a = 0;
|
||||
double f = atof(argv[1]);
|
||||
double r = 5.0;
|
||||
float TxH = 30.0;
|
||||
float RxH = 2.0;
|
||||
|
||||
mkdir("tests", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
|
||||
FILE * fh;
|
||||
|
||||
/*fh = fopen("tests/ITM","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.2){
|
||||
point_to_point_ITM(TxH,RxH,15.0,0.005,301.0,f,5,1,0.5,0.5,a,"",errno);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
*/
|
||||
fh = fopen("tests/SUI.1","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = SUIpathLoss(f, TxH, RxH, d,1);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
fh = fopen("tests/COST231.1","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = COST231pathLoss(f, TxH, RxH, d,1);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
|
||||
fh = fopen("tests/ECC33.1","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = ECC33pathLoss(f, TxH, RxH, d,1);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
fh = fopen("tests/Ericsson9999.1","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = EricssonpathLoss(f, TxH, RxH, d,1);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
fh = fopen("tests/FSPL","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = FSPLpathLoss(f, d);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
fh = fopen("tests/Hata.1","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = HATApathLoss(f, TxH, RxH, d, 1);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
fh = fopen("tests/Egli.VHF-UHF","w");
|
||||
for(float d = 0.1; d <= r; d=d+0.1){
|
||||
a = EgliPathLoss(f, TxH, RxH, d);
|
||||
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
|
||||
fh = fopen("tests/gnuplot.plt","w");
|
||||
fprintf(fh,"set terminal jpeg size 800,600\nset output '%.0fMHz_propagation_models.jpg'\nset title '%.0fMHz path loss by propagation model - CloudRF.com'\n",f,f);
|
||||
fprintf(fh,"set key right bottom box\nset style line 1\nset grid\nset xlabel 'Distance KM'\nset ylabel 'Path Loss dB'\n");
|
||||
fprintf(fh,"plot 'FSPL' with lines, 'Hata.1' with lines, 'COST231.1' with lines,'ECC33.1' with lines,'Ericsson9999.1' with lines,'SUI.1' with lines,'Egli.VHF-UHF' with lines");
|
||||
fclose(fh);
|
||||
|
||||
system("cd tests && gnuplot gnuplot.plt");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
2024
src/outputs.cc
Normal file
2024
src/outputs.cc
Normal file
File diff suppressed because it is too large
Load Diff
17
src/outputs.hh
Normal file
17
src/outputs.hh
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _OUTPUT_HH_
|
||||
#define _OUTPUT_HH_
|
||||
|
||||
void DoPathLoss(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
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);
|
||||
void DoLOS(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
void PathReport(struct site source, struct site destination, char *name,
|
||||
char graph_it, int propmodel, int pmenv, double rxGain);
|
||||
void SeriesData(struct site source, struct site destination, char *name,
|
||||
unsigned char fresnel_plot, unsigned char normalised);
|
||||
|
||||
#endif /* _OUTPUT_HH_ */
|
64
src/suitest.cc
Normal file
64
src/suitest.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// use call with log/ln as this may be faster
|
||||
// use constant of value 20.0/log(10.0)
|
||||
static __inline float _20log10f(float x)
|
||||
{
|
||||
return(8.685889f*logf(x));
|
||||
}
|
||||
|
||||
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode)
|
||||
{
|
||||
/*
|
||||
f = Frequency (MHz) 1900 to 11000
|
||||
TxH = Transmitter height (m)
|
||||
RxH = Receiver height (m)
|
||||
d = distance (km)
|
||||
mode A1 = URBAN / OBSTRUCTED
|
||||
mode B2 = SUBURBAN / PARTIALLY OBSTRUCTED
|
||||
mode C3 = RURAL / OPEN
|
||||
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
*/
|
||||
//f /=1e3;
|
||||
d *= 1e3; // km to m
|
||||
|
||||
// Urban (A1) is default
|
||||
float a = 4.6;
|
||||
float b = 0.0075;
|
||||
float c = 12.6;
|
||||
float s = 10.6; // Optional fading value. Max 10.6dB
|
||||
float XhCF = -10.8;
|
||||
|
||||
if (mode == 2) { // Suburban
|
||||
a = 4.0;
|
||||
b = 0.0065;
|
||||
c = 17.1;
|
||||
}
|
||||
if (mode == 3) { // Rural
|
||||
a = 3.6;
|
||||
b = 0.005;
|
||||
c = 20;
|
||||
XhCF = -20;
|
||||
}
|
||||
float d0 = 100;
|
||||
float A = _20log10f((4 * M_PI * d0) / (300.0 / f));
|
||||
float y = a - (b * TxH) + (c / TxH);
|
||||
//Correction factors
|
||||
float Xf = 6.0 * log10(f / 2000.0);
|
||||
float Xh = XhCF * log10(RxH / 2000.0);
|
||||
Xh *=-1;
|
||||
fprintf(stdout,"A %lf y %lf Xf %lf Xh %lf\n",A,y,Xf,Xh);
|
||||
return A + (10 * y * log10(d / d0)) + Xf + Xh + s;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(){
|
||||
|
||||
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,1));
|
||||
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,2));
|
||||
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,3));
|
||||
}
|
246
src/tiles.cc
Normal file
246
src/tiles.cc
Normal file
@@ -0,0 +1,246 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "tiles.hh"
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_LINE 50000
|
||||
|
||||
/* Computes the distance between two long/lat points */
|
||||
double haversine_formula(double th1, double ph1, double th2, double ph2)
|
||||
{
|
||||
#define TO_RAD (3.1415926536 / 180)
|
||||
int R = 6371;
|
||||
double dx, dy, dz;
|
||||
ph1 -= ph2;
|
||||
ph1 *= TO_RAD, th1 *= TO_RAD, th2 *= TO_RAD;
|
||||
dz = sin(th1) - sin(th2);
|
||||
dx = cos(ph1) * cos(th1) - cos(th2);
|
||||
dy = sin(ph1) * cos(th1);
|
||||
return asin(sqrt(dx * dx + dy * dy + dz * dz) / 2) * 2 * R;
|
||||
}
|
||||
|
||||
int tile_load_lidar(tile_t *tile, char *filename){
|
||||
FILE *fd;
|
||||
char line[MAX_LINE];
|
||||
short nextval;
|
||||
char *pch;
|
||||
|
||||
/* Clear the tile data */
|
||||
memset(tile, 0x00, sizeof(tile_t));
|
||||
|
||||
/* Open the file handle and return on error */
|
||||
if ( (fd = fopen(filename,"r")) == NULL )
|
||||
return errno;
|
||||
|
||||
/* This is where we read the header data */
|
||||
/* The string is split for readability but is parsed as a block */
|
||||
if( fscanf(fd,"%*s %d\n" "%*s %d\n" "%*s %lf\n" "%*s %lf\n" "%*s %lf\n" "%*s %d\n",&tile->width,&tile->height,&tile->xll,&tile->yll,&tile->cellsize,(int *)&tile->nodata) != 6 ){
|
||||
fclose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tile->datastart = ftell(fd);
|
||||
|
||||
if(debug){
|
||||
fprintf(stderr,"w:%d h:%d s:%lf\n", tile->width, tile->height, tile->cellsize);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
/* Set the filename */
|
||||
tile->filename = strdup(filename);
|
||||
|
||||
/* Perform xur calcs */
|
||||
tile->xur = tile->xll+(tile->cellsize*tile->width);
|
||||
tile->yur = tile->yll+(tile->cellsize*tile->height);
|
||||
|
||||
if (tile->xur > eastoffset)
|
||||
eastoffset = tile->xur;
|
||||
if (tile->xll < westoffset)
|
||||
westoffset = tile->xll;
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr,"%d, %d, %.7f, %.7f, %.7f, %.7f, %.7f\n",tile->width,tile->height,tile->xll,tile->yll,tile->cellsize,tile->yur,tile->xur);
|
||||
|
||||
// Greenwich straddling hack
|
||||
/* if (tile->xll <= 0 && tile->xur > 0) {
|
||||
tile->xll = (tile->xur - tile->xll); // full width
|
||||
tile->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 (tile->xll >= 0)
|
||||
tile->xll = 360-tile->xll;
|
||||
if(tile->xur >= 0)
|
||||
tile->xur = 360-tile->xur;
|
||||
if(tile->xll < 0)
|
||||
tile->xll = tile->xll * -1;
|
||||
if(tile->xur < 0)
|
||||
tile->xur = tile->xur * -1;
|
||||
// }
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "POST yll %.7f yur %.7f xur %.7f xll %.7f delta %.6f\n", tile->yll, tile->yur, tile->xur, tile->xll, delta);
|
||||
|
||||
/* Read the actual tile data */
|
||||
/* Allocate the array for the lidar data */
|
||||
if ( (tile->data = (short*) calloc(tile->width * tile->height, sizeof(short))) == NULL ) {
|
||||
fclose(fd);
|
||||
free(tile->filename);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
size_t loaded = 0;
|
||||
for (size_t h = 0; h < (unsigned)tile->height; h++) {
|
||||
if (fgets(line, MAX_LINE, fd) != NULL) {
|
||||
pch = strtok(line, " "); // split line into values
|
||||
for (size_t w = 0; w < (unsigned)tile->width && pch != NULL; w++) {
|
||||
/* If the data is less than a *magic* minimum, normalize it to zero */
|
||||
nextval = atoi(pch);
|
||||
if (nextval <= 0)
|
||||
nextval = 0;
|
||||
tile->data[h*tile->width + w] = nextval;
|
||||
loaded++;
|
||||
if ( nextval > tile->max_el )
|
||||
tile->max_el = nextval;
|
||||
if ( nextval < tile->min_el )
|
||||
tile->min_el = nextval;
|
||||
pch = strtok(NULL, " ");
|
||||
}//while
|
||||
} else {
|
||||
fprintf(stderr, "LIDAR error @ h %zu file %s\n", h, filename);
|
||||
}//if
|
||||
}
|
||||
|
||||
double current_res_km = haversine_formula(tile->max_north, tile->max_west, tile->max_north, tile->min_west);
|
||||
tile->precise_resolution = (current_res_km/MAX(tile->width,tile->height)*1000);
|
||||
|
||||
// Round to nearest 0.5
|
||||
tile->resolution = tile->precise_resolution < 0.5f ? 0.5f : ceil((tile->precise_resolution * 2)+0.5) / 2;
|
||||
|
||||
// Positive westing
|
||||
tile->width_deg = tile->max_west - tile->min_west >= 0 ? tile->max_west - tile->min_west : tile->max_west + (360 - tile->min_west);
|
||||
tile->height_deg = tile->max_north - tile->min_north;
|
||||
|
||||
tile->ppdx = tile->width / tile->width_deg;
|
||||
tile->ppdy = tile->height / tile->height_deg;
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr,"Pixels loaded: %zu/%d (PPD %dx%d, Res %f (%.2f))\n", loaded, tile->width*tile->height, tile->ppdx, tile->ppdy, tile->precise_resolution, tile->resolution);
|
||||
|
||||
/* All done, close the LIDAR file */
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tile_rescale
|
||||
* This is used to resample tile data. It is particularly designed for
|
||||
* use with LIDAR tiles where the resolution can be anything up to 2m.
|
||||
* This function is capable of merging neighbouring pixel values
|
||||
* The scaling factor is the distance to merge pixels.
|
||||
* NOTE: This means that new resolutions can only increment in multiples of the original
|
||||
* (ie 2m LIDAR can be 4/6/8/... and 20m can be 40/60)
|
||||
*/
|
||||
int tile_rescale(tile_t *tile, float scale){
|
||||
short *new_data;
|
||||
size_t skip_count = 1;
|
||||
size_t copy_count = 1;
|
||||
|
||||
if (scale == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t new_height = tile->height * scale;
|
||||
size_t new_width = tile->width * scale;
|
||||
|
||||
/* Allocate the array for the lidar data */
|
||||
if ( (new_data = (short*) calloc(new_height * new_width, sizeof(short))) == NULL ) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
tile->max_el = -32768;
|
||||
tile->min_el = 32768;
|
||||
|
||||
/* Making the tile data smaller */
|
||||
if (scale < 1) {
|
||||
skip_count = 1 / scale;
|
||||
} else {
|
||||
copy_count = (size_t) scale;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
fprintf(stderr,"Resampling tile %s [%.1f]:\n\tOld %dx%d. New %zux%zu\n\tScale %f Skip %zu Copy %zu\n", tile->filename, tile->resolution, tile->width, tile->height, new_width, new_height, scale, skip_count, copy_count);
|
||||
fflush(stderr);
|
||||
}
|
||||
/* Nearest neighbour normalization. For each subsample of the original, simply
|
||||
* assign the value in the top left to the new pixel
|
||||
* SOURCE: X / Y
|
||||
* DEST: I / J */
|
||||
|
||||
for (size_t y = 0, j = 0; y < (unsigned)tile->height && j < new_height; y += skip_count, j += copy_count) {
|
||||
|
||||
for (size_t x = 0, i = 0; x < (unsigned)tile->width && i < new_width; x += skip_count, i += copy_count) {
|
||||
|
||||
/* These are for scaling up the data */
|
||||
for (size_t copy_y = 0; copy_y < copy_count; copy_y++) {
|
||||
for (size_t copy_x = 0; copy_x < copy_count; copy_x++) {
|
||||
size_t new_j = j + copy_y;
|
||||
size_t new_i = i + copy_x;
|
||||
/* Do the copy */
|
||||
new_data[ new_j * new_width + new_i ] = tile->data[y * tile->width + x];
|
||||
}
|
||||
}
|
||||
/* Update local min / max values */
|
||||
if (tile->data[y * tile->width + x] > tile->max_el)
|
||||
tile->max_el = tile->data[y * tile->width + x];
|
||||
if (tile->data[y * tile->width + x] < tile->min_el)
|
||||
tile->min_el = tile->data[y * tile->width + x];
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the date in the tile */
|
||||
free(tile->data);
|
||||
tile->data = new_data;
|
||||
|
||||
/* Update the height and width values */
|
||||
tile->height = new_height;
|
||||
tile->width = new_width;
|
||||
tile->resolution *= 1/scale; // A scale of 2 is HALF the resolution
|
||||
tile->ppdx = tile->width / tile->width_deg;
|
||||
tile->ppdy = tile->height / tile->height_deg;
|
||||
// tile->width_deg *= scale;
|
||||
// tile->height_deg *= scale;
|
||||
if (debug)
|
||||
fprintf(stderr, "Resampling complete. New resolution: %.1f\n", tile->resolution);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tile_resize
|
||||
* This function works in conjuntion with resample_data. It takes a
|
||||
* resolution value in meters as its argument. It then calculates the
|
||||
* nearest (via averaging) resample value and calls resample_data
|
||||
*/
|
||||
int tile_resize(tile_t* tile, int resolution){
|
||||
double current_res_km = haversine_formula(tile->max_north, tile->max_west, tile->max_north, tile->min_west);
|
||||
int current_res = (int) ceil((current_res_km/IPPD)*1000);
|
||||
float scaling_factor = resolution / current_res;
|
||||
if (debug)
|
||||
fprintf(stderr, "Resampling: Current %dm Desired %dm Scale %.1f\n", current_res, resolution, scaling_factor);
|
||||
return tile_rescale(tile, scaling_factor);
|
||||
}
|
||||
|
||||
/*
|
||||
* tile_destroy
|
||||
* This function simply destroys any data associated with a tile
|
||||
*/
|
||||
void tile_destroy(tile_t* tile){
|
||||
if (tile->data != NULL)
|
||||
free(tile->data);
|
||||
}
|
||||
|
48
src/tiles.hh
Normal file
48
src/tiles.hh
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _TILES_HH_
|
||||
#define _TILES_HH_
|
||||
|
||||
typedef struct _tile_t{
|
||||
char *filename;
|
||||
union{
|
||||
int cols;
|
||||
int width;
|
||||
};
|
||||
union{
|
||||
int rows;
|
||||
int height;
|
||||
};
|
||||
union{
|
||||
double xll;
|
||||
double max_west;
|
||||
};
|
||||
union{
|
||||
double yll;
|
||||
double min_north;
|
||||
};
|
||||
union{
|
||||
double xur;
|
||||
double min_west;
|
||||
};
|
||||
union{
|
||||
double yur;
|
||||
double max_north;
|
||||
};
|
||||
double cellsize;
|
||||
long long datastart;
|
||||
short nodata;
|
||||
short max_el;
|
||||
short min_el;
|
||||
short *data;
|
||||
float precise_resolution;
|
||||
float resolution;
|
||||
double width_deg;
|
||||
double height_deg;
|
||||
int ppdx;
|
||||
int ppdy;
|
||||
} tile_t, *ptile_t;
|
||||
|
||||
int tile_load_lidar(tile_t*, char *);
|
||||
int tile_rescale(tile_t *, float);
|
||||
void tile_destroy(tile_t *);
|
||||
|
||||
#endif
|
14
test.sh
14
test.sh
@@ -9,15 +9,23 @@ echo "Running 50cm LIDAR test..."
|
||||
./signalserverLIDAR -lid data/sk3587_50cm.asc -lat 53.383 -lon -1.468 -txh 8 -f $FRQ -erp 1 -rxh 2 -m -dbm -rt -90 -o tests/1 -R 0.5 -t
|
||||
echo "Converting to PNG..."
|
||||
convert tests/1.ppm -transparent white -channel Alpha PNG32:tests/1.png
|
||||
rm tests/1.ppm
|
||||
rm tests/1.*cf
|
||||
|
||||
echo "Running 30m Meridian test..."
|
||||
./signalserverLIDAR -lid data/N051E000_AVE_DSM.tif.asc,data/N051W001_AVE_DSM.tif.asc -lat 51.472 -lon 0.0096 -txh 12 -f $FRQ -erp 5 -rxh 2 -m -dbm -rt -100 -o tests/2 -R 10 -t
|
||||
echo "Converting to PNG..."
|
||||
convert tests/2.ppm -transparent white -channel Alpha PNG32:tests/2.png
|
||||
rm tests/2.ppm
|
||||
rm tests/2.*cf
|
||||
|
||||
echo "Running 446 Mhz Antenna and UDT Clutter test..."
|
||||
./signalserver -sdf /mnt/data -lat 42.328889 -lon -87.862500 -txh 300 -rxh 2 -f $FRQ -erp 700 -R 50 -res 600 -rt 39 -ant antenna/DB413-B -rot 180 -udt data/test.udt -pm 1 -t -o tests/ant-udt_test
|
||||
convert tests/ant-udt_test.ppm tests/ant-udt_test.png
|
||||
rm tests/ant-udt_test.ppm
|
||||
rm tests/ant-udt_test.*cf
|
||||
|
||||
echo "Running soak test out to $MAXRAD"
|
||||
|
||||
while [ $RAD -lt $MAXRAD ]; do
|
||||
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius..."
|
||||
time ./signalserver -m -sdf data -lat 51.5 -lon -0.50 -txh 15 -rxh 2 -m -dbm -rt -100 -R $RAD -erp $ERP -f $FRQ -o tests/$RAD -pm 1 -res 1200 -t
|
||||
@@ -25,12 +33,10 @@ while [ $RAD -lt $MAXRAD ]; do
|
||||
rm tests/$RAD.ppm
|
||||
rm tests/$RAD.*cf
|
||||
|
||||
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius (HD mode)..."
|
||||
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius (HD mode)..."
|
||||
time ./signalserverHD -m -sdf data -lat 51.5 -lon -0.50 -txh 15 -rxh 2 -m -dbm -rt -100 -R $RAD -erp $ERP -f $FRQ -o tests/$RAD.hd -pm 1 -res 3600 -t
|
||||
convert tests/$RAD.hd.ppm tests/$RAD.hd.png
|
||||
rm tests/$RAD.hd.ppm
|
||||
rm tests/$RAD.*cf
|
||||
let RAD=RAD+5
|
||||
done
|
||||
|
||||
|
||||
|
@@ -107,15 +107,15 @@ The usgs2sdf utility takes as an argument the name of an uncompressed
|
||||
and record delimited Digital Elevation Model Data (DEM) downloaded from
|
||||
the US Geological Survey, and generates a SPLAT Data File (SDF) compatible
|
||||
with signalserver. usgs2sdf may be invoked manually, or via the
|
||||
postdownload script.
|
||||
postdownload.sh script.
|
||||
|
||||
|
||||
postdownload
|
||||
============
|
||||
postdownload is a front-end to the usgs2sdf utility. postdownload
|
||||
postdownload.sh
|
||||
===============
|
||||
postdownload.sh is a front-end to the usgs2sdf utility. postdownload.sh
|
||||
takes as an argument the name of the gzipped Digital Elevation Model
|
||||
(DEM) downloaded from the US Geological Survey (ie: wilmington-w.gz).
|
||||
postdownload uncompresses the DEM file, adds necessary record delimiters,
|
||||
postdownload.sh uncompresses the DEM file, adds necessary record delimiters,
|
||||
and invokes usgs2sdf to produce a SPLAT! Data File (SDF).
|
||||
|
||||
USGS Digital Elevation Models may be downloaded from:
|
||||
|
4
utils/sdf/convert_sdf.sh
Executable file
4
utils/sdf/convert_sdf.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
for file in *hgt
|
||||
do
|
||||
sudo ./srtm2sdf -d /dev/null $file
|
||||
done
|
4
utils/sdf/convert_sdf_hd.sh
Executable file
4
utils/sdf/convert_sdf_hd.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
for file in *hgt
|
||||
do
|
||||
sudo ./srtm2sdf-hd -d /dev/null $file
|
||||
done
|
33
utils/sdf/postdownload.sh
Executable file
33
utils/sdf/postdownload.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Simple script for processing of downloaded undelimited gzipped
|
||||
# USGS DEM files, and converting them to SPLAT Data Files.
|
||||
# Written by John A. Magliacane, KD2BD May 2002.
|
||||
# Last modified on Sunday 01-Mar-09.
|
||||
|
||||
if [ "$#" = "0" ]; then
|
||||
echo
|
||||
echo "This utility reads downloaded gzipped USGS DEM"
|
||||
echo "files and generates equivalent SPLAT Data Files (SDFs)."
|
||||
echo
|
||||
echo "Files compatible with this SPLAT! utility may be"
|
||||
echo "obtained at:"
|
||||
echo
|
||||
echo "http://edcftp.cr.usgs.gov/pub/data/DEM/250/"
|
||||
echo
|
||||
echo "Usage: postdownload.sh wilmington-w.gz"
|
||||
echo
|
||||
else
|
||||
# gunzip the downloaded file...
|
||||
echo -n "Uncompressing $1..."
|
||||
gunzip -c $1 > unzipped_file
|
||||
echo
|
||||
echo "Adding record delimiters..."
|
||||
dd if=unzipped_file of=delimited_file ibs=4096 cbs=1024 conv=unblock
|
||||
# Invoke usgs2sdf to generate a SPLAT Data File...
|
||||
usgs2sdf delimited_file
|
||||
echo -n "Removing temp files..."
|
||||
rm delimited_file unzipped_file
|
||||
echo
|
||||
echo "Done!"
|
||||
fi
|
Reference in New Issue
Block a user