This commit is contained in:
N9OZB
2019-07-20 05:52:03 -05:00
parent 047c2f9d27
commit c20c92fcfb
119 changed files with 0 additions and 14439089 deletions

13
.gitignore vendored
View File

@@ -1,13 +0,0 @@
# Compiled Object files
*.slo
*.lo
*.o
# Compiled Dynamic libraries
*.so
*.dylib
# Compiled Static libraries
*.lai
*.la
*.a

230
CHANGELOG
View File

@@ -1,230 +0,0 @@
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.
3.10 - 15 Apr 2018
360 min_west fix
3.09 - 7 Feb 2018
Meridian LIDAR cropping fix
3.08 - 17 Dec 2017
Proper fix for nearfield void
More LIDAR edge cases: 1x2, 2x1...
Removed exit() if no colour file
Polyfilla for gaps at tile edges
SUI model clutter factor
3.07 - 2 Sep 2017
Bugfixes for LIDAR edge cases with mismatched tiles, missing tiles etc.
3.06 - 23 June 2017
Cropping edge cases with > 100km and LOS
3.05 - 18 June 2017
LIDAR overhaul for mismatched tiles and different resolutions. No longer expects x/y grid of tiles of equal size.
Dynamic resampling so user can specify *any* resolution less than maximum resolution of data.
3.04 - 19 April 2017
Added Egli VHF/UHF model courtesy of G6DTX
Adjusted SUI correction factor for height. Most academic papers have /2000 but some are /2. Only out by 1e3 :O
New propagation model unit test script at models/test.cc
Added 10 to ARRAYSIZE again as it was needed :p
3.03 - 19 March 2017
Path profile bugfix for some models
Error handling for when prop loss < free space loss
3.02 - 22 Feb 2017
Gareth's error handling
3.01 - 16 Feb 2017
Image crop (Major performance improvement later on), SUI bugfix, txelev replaced
3.0 - 02 Feb 2017
Image rendering library support. Uses third party PNG lib instead of expensive PPM.
Code cleanup by a professional developer.
More errors to stderr
2.94 - 03 Oct 2016
Reduced MAXPAGES array for LIDAR to allow for uber large tiles
2.93 - 30 Sep 2016
More tiles
2.92 - 29 September 2016
Overhauled LIDAR functions to read in (more) native format tiles.
Replaced 'super tile' code with more scalable multi-tile code: currently limited to 16.
2.9 - 01 September 2016
MODIS Landcover support in ASCII Grid format. Works for 1200/3600 SRTM only.
2.82 - 15 July 2016
Fixed bug in SUI model which was making it over optimistic.
2.81 - 01 July 2016
Added Rx gain value for PPA report only and tweaked text report to show ERP/EIRP with and without Rx gain
2.8 - 08 June 2016
Widened scope of LIDAR / ASCII Grid input to include sub-meter accurate tiles. (ac000)
Optimised memory usage (ac000)
Tidied and refactored some code (ac000)
Updated Readme and callsign because I passed my intermediate :)
2.75 - 22 Apr 2016
Added Hata model logic for f < 200MHz
2.72 - 07 Feb 2016
Expanded LIDAR coverage to read in 4 adjacent ASCII tiles in a 2x2 grid
Removed requirement to specify -res in LIDAR mode as it's in the file header
2.71 - 14 Jan 2016
LIDAR longitude bugfix for Greenwich meridian tiles
Adjusted ITM parameters warnings
2.7 - 03 Jan 2016
Added support for LIDAR data in ASCII grid format with WGS84 bounds
Increased resolution to +54000 pixels per degree (2m)
Removed support for Windows SDF filenames without:colons.
2.63 - 10 Nov 2015
Added sanity check and handicap to ECC33 model when used with low Tx heights in hilly areas = sea of red
2.62 - 30 Oct 2015
Fixed near field 'lattice' bug at 30m resolution caused by previous fix to fill in void around antenna.
Credit to Nils Lofstad for helping nail this down.
2.61 - 27 Oct 2015
FSPL model floor reduced from 150MHz to 20MHz.
2.6 - 9 June 2015
Multi-threading support added by Michael Ramnarine
PlotPropagation() and PlotLOSMap() use four threads by default
Feature can be disabled with -nothreads flag
Static and global variables have been made thread safe
2.5 - 27 May 2015
Code refactored by Andrew Clayton / ac000 with header files
New Makefile with c / c++ multi mode compilation
Single executable now with run time switch for HD mode
Models separated into directory
2.44 - 25 Mar 2015
Improved PPA text report to list other prop models
Added HD mode to build script
2.43 - 06 Mar 2015
Improved model error handling
Tweaked params for Ericsson model and inverted environment variables to match rest
v2.41 - 27 February 2015
Simpler PPA output for scripting
Enabled new models for PPA (previously just ITM)
#Define to enable HD mem options/build at build time (-DHD)
Optimised build command (-Ofast) to improve speed by 14%
Improved test script
2.4 - January 2015
Added SUI, ECC33, Ericsson models in new 'models' module
Added model validation
Retired individual model files as some models only 1 or 2 lines of code
2.31 - October 2014
ERP up to 5MW for Mexican TV(!)
2.3 - 29 September 2014
Replaced itm.cpp with itwom3.0.cpp and added ITWOM model as result
2.23 - 14 August 2014
Improved diffraction model to work only for dips deeper than 20m and not to exaggerate result by an arbitrary figure (3)
Fixed false 'frequency too low' error message for FSPL model which was intended for Hata models only.
2.22 -
Fixed LOS not outputting bounds
2.2 -
Made .dot output opt in to save some disk space
Changed version number to line 1 of main.cpp instead of buried in code in two places.
v2.1 -
Added experimental dual core support with -haf
Requires double the RAM
1.3.8 - 16 Jan 2014
Added Free Space Path Loss model (with optional diffraction)
1.3.7 - 30 Dec 2013
Added propagation model option (-pm)
Added HATA urban/suburban/open models (150-1500MHz)
Added COST231-Hata (urban) model (1500-2000MHz)
Added custom Knife Edge Diffraction option (-ked) to enhance new models
Removed unused variables
1.3.6 - 12 Aug 2013
Added LOS model for up to 100GHz
Added 1 arc second (3600 pixels/degree) support (-res 3600)
1.3.5 - 07 Jul 2013
Reduced maxpages to 9
Added memset() to clear DEM before use
1.3.4 - 16 May 2013
High resolution SRTM1 1-arc second DEM support added.
Use -res 3600 and ensure .sdf files are produced with srtm2sdf-hd
1.3.3 - 04 Nov 2012
Air planning:
Increased maximum Tx height to 60,000 (m/f)
Increased maximum Rx height to 60,000 (m/f)
1.3.2 - 04 Oct 2012
Re-instated grey scale option to allow for terrain background.
Off by default. Enable with switch -t
1.3 - 03 Jan 2012
Added user defined clutter layers from SPLAT! (-udt switch)
1.2 - 31 Dec 2011
Max colours increased from 32 to 128
Radius value fixed at metric
Metric / Imperial conversion bug fixed
1.1 - 08 Dec 2011
Max Tx altitude increased to 20,000(m) for high altitude aircraft. "Can you 'ere me now?"
Added 2 new options -tercon, -terdic for *custom* dielectric values and ground conductivity. -te terrain option remains. Use with care!
New Earth Dielectric range (Permittivity): 80 to 0.1
New Conductivity range (Siemens/m): 0.01 to 0.000001
1.0 - 19 November 2011
Signal Server forked from SPLAT!

339
LICENSE
View File

@@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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
(at your option) any later version.
This program is distributed in the hope that it will be 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -1,59 +0,0 @@
SHELL = /bin/sh
CC = gcc
CXX = g++
CFLAGS = -Wall -O3 -s -ffast-math -DCROPPING
CXXFLAGS = -Wall -O3 -s -ffast-math
LIBS = -lm -lpthread -ldl
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
inputs.o: inputs.cc common.h main.hh
outputs.o: outputs.cc common.h inputs.hh main.hh cost.hh ecc33.hh ericsson.hh \
fspl.hh hata.hh itwom3.0.hh sui.hh pel.hh egli.hh soil.hh
image.o: image.cc image-ppm.o
image-ppm.o: image-ppm.cc
los.o: los.cc common.h 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
.PHONY: clean
clean:
rm -f $(objects) signalserver signalserverHD signalserverLIDAR

218
README.md
View File

@@ -1,218 +0,0 @@
# Signal Server
Multi-threaded radio propagation simulator based upon SPLAT! by Alex Farrant QCVS, 2E0TDW.
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.
## Requirements
* Linux
* GCC,G++
* Multicore CPU (optional)
* ~2GB Memory
* SRTM terrain tile(s) or ASCII Grid tile(s)
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 .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
```
cd src
make install
```
## Test
```
./test.sh
```
## Parameters
```
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] [antenna options] [output options] -o outputfile
Data:
-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
-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 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 - 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-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:
-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)
-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, 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
-ng Normalise Path Profile graph
-haf Halve 1 or 2 (optional)
-nothreads Turn off threaded processing
```
### 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.
#### -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
nrows 1467
xllcorner -1.475333294357
yllcorner 53.378635095801
cellsize 0.000006170864
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.
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. 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
1 0.8966406
2 0.8981447
3 0.8995795
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. 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, 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
-9.5 0.109
-9.0 0.115
-8.5 0.155
-8.0 0.157
```
## Examples
### 90m resolution
- INPUTS: 900MHz tower at 25m AGL with 5W ERP, 30km radius
- OUTPUTS: 1200 resolution, 30km radius, -90dBm receiver threshold, Longley Rice model
```
./signalserver -sdf /data/SRTM3 -lat 51.849 -lon -2.2299 -txh 25 -f 900 -erp 5 -rxh 2 -rt -90 -dbm -m -o test1 -R 30 -res 1200 -pm 1
```
### 30m resolution
- INPUTS: 450MHz tower at 25f AGL with 20W ERP, 10km radius
- OUTPUTS: 3600 resolution, 30km radius, 10dBuV receiver threshold, Hata model
```
./signalserverHD -sdf /data/SRTM1 -lat 51.849 -lon -2.2299 -txh 25 -f 450 -erp 20 -rxh 2 -rt 10 -o test2 -R 10 -res 3600 -pm 3
```
### 2m resolution (LIDAR)
- INPUTS: 1800MHz tower at 15m AGL with 1W ERP, 1 km radius
- OUTPUTS: 2m LIDAR resolution, 5km radius, -90dBm receiver threshold, Longley Rice model
```
./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

Binary file not shown.

View File

@@ -1,720 +0,0 @@
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

View File

@@ -1,361 +0,0 @@
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

View File

@@ -1,102 +0,0 @@
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

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 0, 0, 0
0: 0, 0, 0

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 0, 0, 255
0: 0, 0, 255

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 0, 255, 255
0: 0, 255, 255

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 0, 255, 0
0: 0, 255, 0

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 255, 0, 255
0: 255, 0, 255

View File

@@ -1,16 +0,0 @@
+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

View File

@@ -1,13 +0,0 @@
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

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 255, 0, 0
0: 255, 0, 0

View File

@@ -1,3 +0,0 @@
200: 255, 255, 255
59: 255, 255, 0
0: 255, 255, 0

131
common.h
View File

@@ -1,131 +0,0 @@
#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_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -1,11 +0,0 @@
// 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

View File

@@ -1,42 +0,0 @@
#!/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

View File

@@ -1,59 +0,0 @@
#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;
}

View File

@@ -1,23 +0,0 @@
#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
image.cc
View File

@@ -1,275 +0,0 @@
/*
* 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;
}

View File

@@ -1,63 +0,0 @@
#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

1861
inputs.cc

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
#ifndef _INPUTS_HH_
#define _INPUTS_HH_
#include "common.h"
/* Resample input tiles to new resolution */
int resample_data(int scaling_factor);
int resize_data(int resolution);
int LoadSDF_SDF(char *name, int winfiles);
int LoadSDF(char *name, int winfiles);
int LoadPAT(char *az_filename, char *el_filename);
int LoadSignalColors(struct site xmtr);
int LoadLossColors(struct site xmtr);
int LoadDBMColors(struct site xmtr);
int LoadTopoData(int max_lon, int min_lon, int max_lat, int 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_ */

1968
main.cc

File diff suppressed because it is too large Load Diff

32
main.hh
View File

@@ -1,32 +0,0 @@
#ifndef _MAIN_HH_
#define _MAIN_HH_
#include <stdio.h>
#include "common.h"
int ReduceAngle(double angle);
double LonDiff(double lon1, double lon2);
int PutMask(double lat, double lon, int value);
int OrMask(double lat, double lon, int value);
int GetMask(double lat, double lon);
int 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 alloc_elev(void);
void alloc_path(void);
void do_allocs(void);
#endif /* _MAIN_HH_ */

View File

@@ -1,9 +0,0 @@
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

View File

@@ -1,61 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _COST_HH_
#define _COST_HH_
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _COST_HH_ */

View File

@@ -1,33 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _ECC33_HH_
#define _ECC33_HH_
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _ECC33_HH_ */

View File

@@ -1,83 +0,0 @@
/*****************************************************************************
* 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);
}

View File

@@ -1,6 +0,0 @@
#ifndef _EGLI_HH_
#define _EGLI_HH_
double EgliPathLoss(float f, float h1, float h2, float d);
#endif /* _EGLI_HH_ */

View File

@@ -1,31 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _ERICSSON_HH_
#define _ERICSSON_HH_
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _ERICSSON_HH_ */

View File

@@ -1,33 +0,0 @@
/*****************************************************************************
* 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));
}

View File

@@ -1,6 +0,0 @@
#ifndef _FSPL_HH_
#define _FSPL_HH_
double FSPLpathLoss(float f, float d);
#endif /* _FSPL_HH_ */

View File

@@ -1,58 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _HATA_HH_
#define _HATA_HH_
double HATApathLoss(float f, float h_B, float h_M, float d, int mode);
#endif /* _HATA_HH_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
#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_ */

View File

@@ -1,948 +0,0 @@
#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\"\nout 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);
}
}
}

View File

@@ -1,18 +0,0 @@
#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_ */

View File

@@ -1,29 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _PEL_HH_
#define _PEL_HH_
double PlaneEarthLoss(float d, float TxH, float RxH);
#endif /* _PEL_HH_ */

View File

@@ -1,33 +0,0 @@
/*****************************************************************************
* 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));
}

View File

@@ -1,6 +0,0 @@
#ifndef _SOIL_HH_
#define _SOIL_HH_
double SoilPathLoss(float f, float d, float t);
#endif /* _SOIL_HH_ */

View File

@@ -1,65 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _SUI_HH_
#define _SUI_HH_
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
#endif /* _SUI_HH_ */

View File

@@ -1,117 +0,0 @@
#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);
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);
}

2014
outputs.cc

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
#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_ */

View File

@@ -1,18 +0,0 @@
#!/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

View File

@@ -1,77 +0,0 @@
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)

View File

@@ -1,131 +0,0 @@
#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_ */

View File

@@ -1,59 +0,0 @@
#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;
}

View File

@@ -1,23 +0,0 @@
#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

View File

@@ -1,275 +0,0 @@
/*
* 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;
}

View File

@@ -1,63 +0,0 @@
#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

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
#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_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +0,0 @@
#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_ */

View File

@@ -1,9 +0,0 @@
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

View File

@@ -1,61 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _COST_HH_
#define _COST_HH_
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _COST_HH_ */

View File

@@ -1,33 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _ECC33_HH_
#define _ECC33_HH_
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _ECC33_HH_ */

View File

@@ -1,83 +0,0 @@
/*****************************************************************************
* 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);
}

View File

@@ -1,6 +0,0 @@
#ifndef _EGLI_HH_
#define _EGLI_HH_
double EgliPathLoss(float f, float h1, float h2, float d);
#endif /* _EGLI_HH_ */

View File

@@ -1,31 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _ERICSSON_HH_
#define _ERICSSON_HH_
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
#endif /* _ERICSSON_HH_ */

View File

@@ -1,33 +0,0 @@
/*****************************************************************************
* 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));
}

View File

@@ -1,6 +0,0 @@
#ifndef _FSPL_HH_
#define _FSPL_HH_
double FSPLpathLoss(float f, float d);
#endif /* _FSPL_HH_ */

View File

@@ -1,58 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _HATA_HH_
#define _HATA_HH_
double HATApathLoss(float f, float h_B, float h_M, float d, int mode);
#endif /* _HATA_HH_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
#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_ */

View File

@@ -1,948 +0,0 @@
#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);
}
}
}

View File

@@ -1,18 +0,0 @@
#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_ */

View File

@@ -1,29 +0,0 @@
/*****************************************************************************
* 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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _PEL_HH_
#define _PEL_HH_
double PlaneEarthLoss(float d, float TxH, float RxH);
#endif /* _PEL_HH_ */

View File

@@ -1,33 +0,0 @@
/*****************************************************************************
* 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));
}

View File

@@ -1,6 +0,0 @@
#ifndef _SOIL_HH_
#define _SOIL_HH_
double SoilPathLoss(float f, float d, float t);
#endif /* _SOIL_HH_ */

View File

@@ -1,65 +0,0 @@
#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;
}

View File

@@ -1,6 +0,0 @@
#ifndef _SUI_HH_
#define _SUI_HH_
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
#endif /* _SUI_HH_ */

View File

@@ -1,118 +0,0 @@
#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);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
#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_ */

Some files were not shown because too many files have changed in this diff Show More