forked from ExternalVendorCode/Signal-Server
Initial Commit
This commit is contained in:
230
CHANGELOG
Executable file
230
CHANGELOG
Executable file
@@ -0,0 +1,230 @@
|
|||||||
|
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
Normal file
339
LICENSE
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
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.
|
218
README.md
Normal file
218
README.md
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
# 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
|
BIN
SignalServer_Manual.odt
Normal file
BIN
SignalServer_Manual.odt
Normal file
Binary file not shown.
720
antenna/DB413-B.ant
Normal file
720
antenna/DB413-B.ant
Normal file
@@ -0,0 +1,720 @@
|
|||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.4
|
||||||
|
-0.4
|
||||||
|
-0.4
|
||||||
|
-0.5
|
||||||
|
-0.5
|
||||||
|
-0.5
|
||||||
|
-0.6
|
||||||
|
-0.6
|
||||||
|
-0.6
|
||||||
|
-0.7
|
||||||
|
-0.7
|
||||||
|
-0.8
|
||||||
|
-0.8
|
||||||
|
-0.8
|
||||||
|
-0.9
|
||||||
|
-0.9
|
||||||
|
-1
|
||||||
|
-1
|
||||||
|
-1.1
|
||||||
|
-1.1
|
||||||
|
-1.2
|
||||||
|
-1.2
|
||||||
|
-1.3
|
||||||
|
-1.4
|
||||||
|
-1.4
|
||||||
|
-1.5
|
||||||
|
-1.5
|
||||||
|
-1.6
|
||||||
|
-1.6
|
||||||
|
-1.7
|
||||||
|
-1.8
|
||||||
|
-1.9
|
||||||
|
-1.9
|
||||||
|
-2
|
||||||
|
-2.1
|
||||||
|
-2.1
|
||||||
|
-2.2
|
||||||
|
-2.3
|
||||||
|
-2.4
|
||||||
|
-2.5
|
||||||
|
-2.5
|
||||||
|
-2.6
|
||||||
|
-2.7
|
||||||
|
-2.8
|
||||||
|
-2.9
|
||||||
|
-3
|
||||||
|
-3
|
||||||
|
-3.1
|
||||||
|
-3.2
|
||||||
|
-3.3
|
||||||
|
-3.4
|
||||||
|
-3.5
|
||||||
|
-3.6
|
||||||
|
-3.7
|
||||||
|
-3.8
|
||||||
|
-3.9
|
||||||
|
-4
|
||||||
|
-4.1
|
||||||
|
-4.3
|
||||||
|
-4.4
|
||||||
|
-4.5
|
||||||
|
-4.6
|
||||||
|
-4.7
|
||||||
|
-4.8
|
||||||
|
-4.9
|
||||||
|
-5
|
||||||
|
-5.2
|
||||||
|
-5.3
|
||||||
|
-5.4
|
||||||
|
-5.5
|
||||||
|
-5.6
|
||||||
|
-5.8
|
||||||
|
-5.9
|
||||||
|
-6
|
||||||
|
-6.1
|
||||||
|
-6.2
|
||||||
|
-6.4
|
||||||
|
-6.5
|
||||||
|
-6.6
|
||||||
|
-6.7
|
||||||
|
-6.8
|
||||||
|
-7
|
||||||
|
-7.1
|
||||||
|
-7.2
|
||||||
|
-7.3
|
||||||
|
-7.4
|
||||||
|
-7.6
|
||||||
|
-7.7
|
||||||
|
-7.8
|
||||||
|
-7.9
|
||||||
|
-8
|
||||||
|
-8.1
|
||||||
|
-8.2
|
||||||
|
-8.3
|
||||||
|
-8.4
|
||||||
|
-8.5
|
||||||
|
-8.6
|
||||||
|
-8.7
|
||||||
|
-8.8
|
||||||
|
-8.9
|
||||||
|
-8.9
|
||||||
|
-9
|
||||||
|
-9.1
|
||||||
|
-9.2
|
||||||
|
-9.2
|
||||||
|
-9.3
|
||||||
|
-9.3
|
||||||
|
-9.4
|
||||||
|
-9.4
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.8
|
||||||
|
-9.8
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.8
|
||||||
|
-9.8
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.6
|
||||||
|
-9.5
|
||||||
|
-9.5
|
||||||
|
-9.4
|
||||||
|
-9.4
|
||||||
|
-9.3
|
||||||
|
-9.3
|
||||||
|
-9.2
|
||||||
|
-9.2
|
||||||
|
-9.1
|
||||||
|
-9
|
||||||
|
-8.9
|
||||||
|
-8.9
|
||||||
|
-8.8
|
||||||
|
-8.7
|
||||||
|
-8.6
|
||||||
|
-8.5
|
||||||
|
-8.4
|
||||||
|
-8.3
|
||||||
|
-8.2
|
||||||
|
-8.1
|
||||||
|
-8
|
||||||
|
-7.9
|
||||||
|
-7.8
|
||||||
|
-7.7
|
||||||
|
-7.6
|
||||||
|
-7.4
|
||||||
|
-7.3
|
||||||
|
-7.2
|
||||||
|
-7.1
|
||||||
|
-7
|
||||||
|
-6.8
|
||||||
|
-6.7
|
||||||
|
-6.6
|
||||||
|
-6.5
|
||||||
|
-6.4
|
||||||
|
-6.2
|
||||||
|
-6.1
|
||||||
|
-6
|
||||||
|
-5.9
|
||||||
|
-5.8
|
||||||
|
-5.6
|
||||||
|
-5.5
|
||||||
|
-5.4
|
||||||
|
-5.3
|
||||||
|
-5.2
|
||||||
|
-5
|
||||||
|
-4.9
|
||||||
|
-4.8
|
||||||
|
-4.7
|
||||||
|
-4.6
|
||||||
|
-4.5
|
||||||
|
-4.4
|
||||||
|
-4.3
|
||||||
|
-4.1
|
||||||
|
-4
|
||||||
|
-3.9
|
||||||
|
-3.8
|
||||||
|
-3.7
|
||||||
|
-3.6
|
||||||
|
-3.5
|
||||||
|
-3.4
|
||||||
|
-3.3
|
||||||
|
-3.2
|
||||||
|
-3.1
|
||||||
|
-3
|
||||||
|
-3
|
||||||
|
-2.9
|
||||||
|
-2.8
|
||||||
|
-2.7
|
||||||
|
-2.6
|
||||||
|
-2.5
|
||||||
|
-2.5
|
||||||
|
-2.4
|
||||||
|
-2.3
|
||||||
|
-2.2
|
||||||
|
-2.1
|
||||||
|
-2.1
|
||||||
|
-2
|
||||||
|
-1.9
|
||||||
|
-1.9
|
||||||
|
-1.8
|
||||||
|
-1.7
|
||||||
|
-1.6
|
||||||
|
-1.6
|
||||||
|
-1.5
|
||||||
|
-1.5
|
||||||
|
-1.4
|
||||||
|
-1.4
|
||||||
|
-1.3
|
||||||
|
-1.2
|
||||||
|
-1.2
|
||||||
|
-1.1
|
||||||
|
-1.1
|
||||||
|
-1
|
||||||
|
-1
|
||||||
|
-0.9
|
||||||
|
-0.9
|
||||||
|
-0.8
|
||||||
|
-0.8
|
||||||
|
-0.8
|
||||||
|
-0.7
|
||||||
|
-0.7
|
||||||
|
-0.6
|
||||||
|
-0.6
|
||||||
|
-0.6
|
||||||
|
-0.5
|
||||||
|
-0.5
|
||||||
|
-0.5
|
||||||
|
-0.4
|
||||||
|
-0.4
|
||||||
|
-0.4
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.3
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.2
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
-0.1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
-40
|
||||||
|
-32.8
|
||||||
|
-26.7
|
||||||
|
-23.1
|
||||||
|
-20.6
|
||||||
|
-18.6
|
||||||
|
-17
|
||||||
|
-15.6
|
||||||
|
-14.4
|
||||||
|
-13.4
|
||||||
|
-12.5
|
||||||
|
-11.7
|
||||||
|
-11
|
||||||
|
-10.5
|
||||||
|
-10
|
||||||
|
-9.6
|
||||||
|
-9.3
|
||||||
|
-9.1
|
||||||
|
-9.1
|
||||||
|
-9.1
|
||||||
|
-9.4
|
||||||
|
-9.7
|
||||||
|
-10.3
|
||||||
|
-11.2
|
||||||
|
-12.3
|
||||||
|
-13.8
|
||||||
|
-15.8
|
||||||
|
-18.4
|
||||||
|
-21.8
|
||||||
|
-23.9
|
||||||
|
-21.9
|
||||||
|
-19
|
||||||
|
-16.8
|
||||||
|
-15.3
|
||||||
|
-14.5
|
||||||
|
-14.2
|
||||||
|
-14.4
|
||||||
|
-15.2
|
||||||
|
-16.7
|
||||||
|
-19.2
|
||||||
|
-23
|
||||||
|
-27.9
|
||||||
|
-26.5
|
||||||
|
-22.2
|
||||||
|
-19.5
|
||||||
|
-18.2
|
||||||
|
-17.8
|
||||||
|
-18.3
|
||||||
|
-19.8
|
||||||
|
-22.5
|
||||||
|
-26.7
|
||||||
|
-28.3
|
||||||
|
-24.4
|
||||||
|
-21.3
|
||||||
|
-19.7
|
||||||
|
-19.2
|
||||||
|
-19.7
|
||||||
|
-21.3
|
||||||
|
-24.2
|
||||||
|
-27.9
|
||||||
|
-27.1
|
||||||
|
-23.4
|
||||||
|
-21
|
||||||
|
-19.8
|
||||||
|
-19.8
|
||||||
|
-20.9
|
||||||
|
-23.4
|
||||||
|
-27.4
|
||||||
|
-27.8
|
||||||
|
-23.2
|
||||||
|
-20.1
|
||||||
|
-18.4
|
||||||
|
-18.1
|
||||||
|
-19.1
|
||||||
|
-22.2
|
||||||
|
-28.2
|
||||||
|
-24.9
|
||||||
|
-18.8
|
||||||
|
-15.5
|
||||||
|
-14
|
||||||
|
-14
|
||||||
|
-15.9
|
||||||
|
-22
|
||||||
|
-23.5
|
||||||
|
-13.2
|
||||||
|
-8
|
||||||
|
-4.7
|
||||||
|
-2.5
|
||||||
|
-1
|
||||||
|
-0.2
|
||||||
|
0
|
||||||
|
-0.3
|
||||||
|
-1.3
|
||||||
|
-2.9
|
||||||
|
-5.4
|
||||||
|
-9.3
|
||||||
|
-16
|
||||||
|
-40
|
||||||
|
-18.5
|
||||||
|
-14.4
|
||||||
|
-13.3
|
||||||
|
-13.9
|
||||||
|
-16.1
|
||||||
|
-20.2
|
||||||
|
-26.7
|
||||||
|
-25.3
|
||||||
|
-21
|
||||||
|
-19.1
|
||||||
|
-18.9
|
||||||
|
-19.9
|
||||||
|
-21.9
|
||||||
|
-24.6
|
||||||
|
-26.4
|
||||||
|
-25.4
|
||||||
|
-23.5
|
||||||
|
-22.2
|
||||||
|
-21.5
|
||||||
|
-21.4
|
||||||
|
-22.1
|
||||||
|
-23.6
|
||||||
|
-26.1
|
||||||
|
-28.5
|
||||||
|
-27.2
|
||||||
|
-24.1
|
||||||
|
-21.9
|
||||||
|
-20.8
|
||||||
|
-20.7
|
||||||
|
-21.8
|
||||||
|
-24.4
|
||||||
|
-29.8
|
||||||
|
-34.8
|
||||||
|
-26.9
|
||||||
|
-22.5
|
||||||
|
-20.1
|
||||||
|
-19
|
||||||
|
-18.9
|
||||||
|
-19.7
|
||||||
|
-21.7
|
||||||
|
-25.5
|
||||||
|
-34.3
|
||||||
|
-34.3
|
||||||
|
-25.4
|
||||||
|
-21.5
|
||||||
|
-19.5
|
||||||
|
-18.4
|
||||||
|
-18.2
|
||||||
|
-18.8
|
||||||
|
-20.2
|
||||||
|
-23
|
||||||
|
-28.5
|
||||||
|
-37.7
|
||||||
|
-26.2
|
||||||
|
-20.7
|
||||||
|
-17.4
|
||||||
|
-15
|
||||||
|
-13.4
|
||||||
|
-12.1
|
||||||
|
-11.2
|
||||||
|
-10.6
|
||||||
|
-10.1
|
||||||
|
-9.8
|
||||||
|
-9.7
|
||||||
|
-9.7
|
||||||
|
-9.9
|
||||||
|
-10.1
|
||||||
|
-10.5
|
||||||
|
-10.9
|
||||||
|
-11.5
|
||||||
|
-12.1
|
||||||
|
-12.8
|
||||||
|
-13.6
|
||||||
|
-14.6
|
||||||
|
-15.6
|
||||||
|
-16.8
|
||||||
|
-18.2
|
||||||
|
-19.8
|
||||||
|
-21.8
|
||||||
|
-24.4
|
||||||
|
-27.9
|
||||||
|
-34
|
||||||
|
-40
|
||||||
|
-34
|
||||||
|
-28
|
||||||
|
-24.5
|
||||||
|
-22
|
||||||
|
-20
|
||||||
|
-18.4
|
||||||
|
-17.1
|
||||||
|
-15.9
|
||||||
|
-14.9
|
||||||
|
-14
|
||||||
|
-13.2
|
||||||
|
-12.5
|
||||||
|
-11.9
|
||||||
|
-11.4
|
||||||
|
-11
|
||||||
|
-10.7
|
||||||
|
-10.5
|
||||||
|
-10.4
|
||||||
|
-10.4
|
||||||
|
-10.6
|
||||||
|
-10.9
|
||||||
|
-11.4
|
||||||
|
-12.1
|
||||||
|
-13.1
|
||||||
|
-14.4
|
||||||
|
-16.1
|
||||||
|
-18.5
|
||||||
|
-21.8
|
||||||
|
-26.7
|
||||||
|
-30.3
|
||||||
|
-26
|
||||||
|
-22.3
|
||||||
|
-20
|
||||||
|
-18.7
|
||||||
|
-18.1
|
||||||
|
-18.1
|
||||||
|
-18.8
|
||||||
|
-19.9
|
||||||
|
-21.6
|
||||||
|
-23.4
|
||||||
|
-24.1
|
||||||
|
-23.2
|
||||||
|
-21.8
|
||||||
|
-20.7
|
||||||
|
-20.3
|
||||||
|
-20.6
|
||||||
|
-21.6
|
||||||
|
-23.5
|
||||||
|
-25.8
|
||||||
|
-27
|
||||||
|
-25.6
|
||||||
|
-23.7
|
||||||
|
-22.5
|
||||||
|
-22.3
|
||||||
|
-22.9
|
||||||
|
-24.5
|
||||||
|
-26.8
|
||||||
|
-28.1
|
||||||
|
-26.8
|
||||||
|
-25
|
||||||
|
-23.9
|
||||||
|
-23.8
|
||||||
|
-24.7
|
||||||
|
-26.4
|
||||||
|
-28.2
|
||||||
|
-28.2
|
||||||
|
-26.8
|
||||||
|
-25.5
|
||||||
|
-25.1
|
||||||
|
-25.6
|
||||||
|
-26.8
|
||||||
|
-28.3
|
||||||
|
-29.4
|
||||||
|
-29.4
|
||||||
|
-28.9
|
||||||
|
-28.3
|
||||||
|
-28.1
|
||||||
|
-28.2
|
||||||
|
-28.5
|
||||||
|
-28.3
|
||||||
|
-26
|
||||||
|
-22.2
|
||||||
|
-18.5
|
||||||
|
-15.4
|
||||||
|
-12.9
|
||||||
|
-11
|
||||||
|
-9.6
|
||||||
|
-8.6
|
||||||
|
-8.1
|
||||||
|
-8
|
||||||
|
-8.5
|
||||||
|
-9.5
|
||||||
|
-11.3
|
||||||
|
-14.2
|
||||||
|
-18.6
|
||||||
|
-23.7
|
||||||
|
-21.2
|
||||||
|
-17.8
|
||||||
|
-16.3
|
||||||
|
-16.3
|
||||||
|
-17.8
|
||||||
|
-21.1
|
||||||
|
-28.5
|
||||||
|
-37.9
|
||||||
|
-25.4
|
||||||
|
-22
|
||||||
|
-21.3
|
||||||
|
-22.5
|
||||||
|
-25.9
|
||||||
|
-33.8
|
||||||
|
-32.2
|
||||||
|
-25.9
|
||||||
|
-23.3
|
||||||
|
-22.8
|
||||||
|
-23.9
|
||||||
|
-26.8
|
||||||
|
-31.4
|
||||||
|
-30.7
|
||||||
|
-26.6
|
||||||
|
-24.3
|
||||||
|
-23.5
|
||||||
|
-24
|
||||||
|
-25.6
|
||||||
|
-27.9
|
||||||
|
-28.7
|
||||||
|
-27.1
|
||||||
|
-25.3
|
||||||
|
-24.2
|
||||||
|
-24.1
|
||||||
|
-24.5
|
||||||
|
-25.2
|
||||||
|
-25.4
|
||||||
|
-24.8
|
||||||
|
-23.8
|
||||||
|
-23.1
|
||||||
|
-22.9
|
||||||
|
-23.3
|
||||||
|
-24.3
|
||||||
|
-25.4
|
||||||
|
-25.5
|
||||||
|
-24
|
||||||
|
-21.9
|
||||||
|
-20.1
|
||||||
|
-18.8
|
||||||
|
-17.9
|
||||||
|
-17.6
|
||||||
|
-17.6
|
||||||
|
-17.9
|
||||||
|
-18.5
|
||||||
|
-19
|
||||||
|
-19.2
|
||||||
|
-18.7
|
||||||
|
-17.6
|
||||||
|
-16.3
|
||||||
|
-15
|
||||||
|
-13.8
|
||||||
|
-12.8
|
||||||
|
-12.1
|
||||||
|
-11.5
|
||||||
|
-11
|
||||||
|
-10.8
|
||||||
|
-10.6
|
||||||
|
-10.6
|
||||||
|
-10.7
|
||||||
|
-10.9
|
||||||
|
-11.2
|
||||||
|
-11.6
|
||||||
|
-12.1
|
||||||
|
-12.7
|
||||||
|
-13.4
|
||||||
|
-14.2
|
||||||
|
-15.1
|
||||||
|
-16.2
|
||||||
|
-17.5
|
||||||
|
-19
|
||||||
|
-20.9
|
||||||
|
-23.4
|
||||||
|
-26.9
|
||||||
|
-32.8
|
361
antenna/DB413-B.az
Normal file
361
antenna/DB413-B.az
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
0
|
||||||
|
0 1.0000
|
||||||
|
1 1.0000
|
||||||
|
2 1.0000
|
||||||
|
3 1.0000
|
||||||
|
4 1.0000
|
||||||
|
5 1.0000
|
||||||
|
6 1.0000
|
||||||
|
7 1.0000
|
||||||
|
8 1.0000
|
||||||
|
9 0.9772
|
||||||
|
10 0.9772
|
||||||
|
11 0.9772
|
||||||
|
12 0.9772
|
||||||
|
13 0.9772
|
||||||
|
14 0.9772
|
||||||
|
15 0.9772
|
||||||
|
16 0.9772
|
||||||
|
17 0.9550
|
||||||
|
18 0.9550
|
||||||
|
19 0.9550
|
||||||
|
20 0.9550
|
||||||
|
21 0.9550
|
||||||
|
22 0.9333
|
||||||
|
23 0.9333
|
||||||
|
24 0.9333
|
||||||
|
25 0.9333
|
||||||
|
26 0.9120
|
||||||
|
27 0.9120
|
||||||
|
28 0.9120
|
||||||
|
29 0.8913
|
||||||
|
30 0.8913
|
||||||
|
31 0.8913
|
||||||
|
32 0.8710
|
||||||
|
33 0.8710
|
||||||
|
34 0.8710
|
||||||
|
35 0.8511
|
||||||
|
36 0.8511
|
||||||
|
37 0.8318
|
||||||
|
38 0.8318
|
||||||
|
39 0.8318
|
||||||
|
40 0.8128
|
||||||
|
41 0.8128
|
||||||
|
42 0.7943
|
||||||
|
43 0.7943
|
||||||
|
44 0.7762
|
||||||
|
45 0.7762
|
||||||
|
46 0.7586
|
||||||
|
47 0.7586
|
||||||
|
48 0.7413
|
||||||
|
49 0.7244
|
||||||
|
50 0.7244
|
||||||
|
51 0.7079
|
||||||
|
52 0.7079
|
||||||
|
53 0.6918
|
||||||
|
54 0.6918
|
||||||
|
55 0.6761
|
||||||
|
56 0.6607
|
||||||
|
57 0.6457
|
||||||
|
58 0.6457
|
||||||
|
59 0.6310
|
||||||
|
60 0.6166
|
||||||
|
61 0.6166
|
||||||
|
62 0.6026
|
||||||
|
63 0.5888
|
||||||
|
64 0.5754
|
||||||
|
65 0.5623
|
||||||
|
66 0.5623
|
||||||
|
67 0.5495
|
||||||
|
68 0.5370
|
||||||
|
69 0.5248
|
||||||
|
70 0.5129
|
||||||
|
71 0.5012
|
||||||
|
72 0.5012
|
||||||
|
73 0.4898
|
||||||
|
74 0.4786
|
||||||
|
75 0.4677
|
||||||
|
76 0.4571
|
||||||
|
77 0.4467
|
||||||
|
78 0.4365
|
||||||
|
79 0.4266
|
||||||
|
80 0.4169
|
||||||
|
81 0.4074
|
||||||
|
82 0.3981
|
||||||
|
83 0.3890
|
||||||
|
84 0.3715
|
||||||
|
85 0.3631
|
||||||
|
86 0.3548
|
||||||
|
87 0.3467
|
||||||
|
88 0.3388
|
||||||
|
89 0.3311
|
||||||
|
90 0.3236
|
||||||
|
91 0.3162
|
||||||
|
92 0.3020
|
||||||
|
93 0.2951
|
||||||
|
94 0.2884
|
||||||
|
95 0.2818
|
||||||
|
96 0.2754
|
||||||
|
97 0.2630
|
||||||
|
98 0.2570
|
||||||
|
99 0.2512
|
||||||
|
100 0.2455
|
||||||
|
101 0.2399
|
||||||
|
102 0.2291
|
||||||
|
103 0.2239
|
||||||
|
104 0.2188
|
||||||
|
105 0.2138
|
||||||
|
106 0.2089
|
||||||
|
107 0.1995
|
||||||
|
108 0.1950
|
||||||
|
109 0.1905
|
||||||
|
110 0.1862
|
||||||
|
111 0.1820
|
||||||
|
112 0.1738
|
||||||
|
113 0.1698
|
||||||
|
114 0.1660
|
||||||
|
115 0.1622
|
||||||
|
116 0.1585
|
||||||
|
117 0.1549
|
||||||
|
118 0.1514
|
||||||
|
119 0.1479
|
||||||
|
120 0.1445
|
||||||
|
121 0.1413
|
||||||
|
122 0.1380
|
||||||
|
123 0.1349
|
||||||
|
124 0.1318
|
||||||
|
125 0.1288
|
||||||
|
126 0.1288
|
||||||
|
127 0.1259
|
||||||
|
128 0.1230
|
||||||
|
129 0.1202
|
||||||
|
130 0.1202
|
||||||
|
131 0.1175
|
||||||
|
132 0.1175
|
||||||
|
133 0.1148
|
||||||
|
134 0.1148
|
||||||
|
135 0.1122
|
||||||
|
136 0.1122
|
||||||
|
137 0.1096
|
||||||
|
138 0.1096
|
||||||
|
139 0.1096
|
||||||
|
140 0.1072
|
||||||
|
141 0.1072
|
||||||
|
142 0.1072
|
||||||
|
143 0.1072
|
||||||
|
144 0.1072
|
||||||
|
145 0.1072
|
||||||
|
146 0.1072
|
||||||
|
147 0.1072
|
||||||
|
148 0.1047
|
||||||
|
149 0.1047
|
||||||
|
150 0.1072
|
||||||
|
151 0.1072
|
||||||
|
152 0.1072
|
||||||
|
153 0.1072
|
||||||
|
154 0.1072
|
||||||
|
155 0.1072
|
||||||
|
156 0.1072
|
||||||
|
157 0.1072
|
||||||
|
158 0.1072
|
||||||
|
159 0.1072
|
||||||
|
160 0.1072
|
||||||
|
161 0.1096
|
||||||
|
162 0.1096
|
||||||
|
163 0.1096
|
||||||
|
164 0.1096
|
||||||
|
165 0.1096
|
||||||
|
166 0.1096
|
||||||
|
167 0.1096
|
||||||
|
168 0.1096
|
||||||
|
169 0.1122
|
||||||
|
170 0.1122
|
||||||
|
171 0.1122
|
||||||
|
172 0.1122
|
||||||
|
173 0.1122
|
||||||
|
174 0.1122
|
||||||
|
175 0.1122
|
||||||
|
176 0.1122
|
||||||
|
177 0.1122
|
||||||
|
178 0.1122
|
||||||
|
179 0.1122
|
||||||
|
180 0.1122
|
||||||
|
181 0.1122
|
||||||
|
182 0.1122
|
||||||
|
183 0.1122
|
||||||
|
184 0.1122
|
||||||
|
185 0.1122
|
||||||
|
186 0.1122
|
||||||
|
187 0.1122
|
||||||
|
188 0.1122
|
||||||
|
189 0.1122
|
||||||
|
190 0.1122
|
||||||
|
191 0.1122
|
||||||
|
192 0.1096
|
||||||
|
193 0.1096
|
||||||
|
194 0.1096
|
||||||
|
195 0.1096
|
||||||
|
196 0.1096
|
||||||
|
197 0.1096
|
||||||
|
198 0.1096
|
||||||
|
199 0.1096
|
||||||
|
200 0.1072
|
||||||
|
201 0.1072
|
||||||
|
202 0.1072
|
||||||
|
203 0.1072
|
||||||
|
204 0.1072
|
||||||
|
205 0.1072
|
||||||
|
206 0.1072
|
||||||
|
207 0.1072
|
||||||
|
208 0.1072
|
||||||
|
209 0.1072
|
||||||
|
210 0.1072
|
||||||
|
211 0.1047
|
||||||
|
212 0.1047
|
||||||
|
213 0.1072
|
||||||
|
214 0.1072
|
||||||
|
215 0.1072
|
||||||
|
216 0.1072
|
||||||
|
217 0.1072
|
||||||
|
218 0.1072
|
||||||
|
219 0.1072
|
||||||
|
220 0.1072
|
||||||
|
221 0.1096
|
||||||
|
222 0.1096
|
||||||
|
223 0.1096
|
||||||
|
224 0.1122
|
||||||
|
225 0.1122
|
||||||
|
226 0.1148
|
||||||
|
227 0.1148
|
||||||
|
228 0.1175
|
||||||
|
229 0.1175
|
||||||
|
230 0.1202
|
||||||
|
231 0.1202
|
||||||
|
232 0.1230
|
||||||
|
233 0.1259
|
||||||
|
234 0.1288
|
||||||
|
235 0.1288
|
||||||
|
236 0.1318
|
||||||
|
237 0.1349
|
||||||
|
238 0.1380
|
||||||
|
239 0.1413
|
||||||
|
240 0.1445
|
||||||
|
241 0.1479
|
||||||
|
242 0.1514
|
||||||
|
243 0.1549
|
||||||
|
244 0.1585
|
||||||
|
245 0.1622
|
||||||
|
246 0.1660
|
||||||
|
247 0.1698
|
||||||
|
248 0.1738
|
||||||
|
249 0.1820
|
||||||
|
250 0.1862
|
||||||
|
251 0.1905
|
||||||
|
252 0.1950
|
||||||
|
253 0.1995
|
||||||
|
254 0.2089
|
||||||
|
255 0.2138
|
||||||
|
256 0.2188
|
||||||
|
257 0.2239
|
||||||
|
258 0.2291
|
||||||
|
259 0.2399
|
||||||
|
260 0.2455
|
||||||
|
261 0.2512
|
||||||
|
262 0.2570
|
||||||
|
263 0.2630
|
||||||
|
264 0.2754
|
||||||
|
265 0.2818
|
||||||
|
266 0.2884
|
||||||
|
267 0.2951
|
||||||
|
268 0.3020
|
||||||
|
269 0.3162
|
||||||
|
270 0.3236
|
||||||
|
271 0.3311
|
||||||
|
272 0.3388
|
||||||
|
273 0.3467
|
||||||
|
274 0.3548
|
||||||
|
275 0.3631
|
||||||
|
276 0.3715
|
||||||
|
277 0.3890
|
||||||
|
278 0.3981
|
||||||
|
279 0.4074
|
||||||
|
280 0.4169
|
||||||
|
281 0.4266
|
||||||
|
282 0.4365
|
||||||
|
283 0.4467
|
||||||
|
284 0.4571
|
||||||
|
285 0.4677
|
||||||
|
286 0.4786
|
||||||
|
287 0.4898
|
||||||
|
288 0.5012
|
||||||
|
289 0.5012
|
||||||
|
290 0.5129
|
||||||
|
291 0.5248
|
||||||
|
292 0.5370
|
||||||
|
293 0.5495
|
||||||
|
294 0.5623
|
||||||
|
295 0.5623
|
||||||
|
296 0.5754
|
||||||
|
297 0.5888
|
||||||
|
298 0.6026
|
||||||
|
299 0.6166
|
||||||
|
300 0.6166
|
||||||
|
301 0.6310
|
||||||
|
302 0.6457
|
||||||
|
303 0.6457
|
||||||
|
304 0.6607
|
||||||
|
305 0.6761
|
||||||
|
306 0.6918
|
||||||
|
307 0.6918
|
||||||
|
308 0.7079
|
||||||
|
309 0.7079
|
||||||
|
310 0.7244
|
||||||
|
311 0.7244
|
||||||
|
312 0.7413
|
||||||
|
313 0.7586
|
||||||
|
314 0.7586
|
||||||
|
315 0.7762
|
||||||
|
316 0.7762
|
||||||
|
317 0.7943
|
||||||
|
318 0.7943
|
||||||
|
319 0.8128
|
||||||
|
320 0.8128
|
||||||
|
321 0.8318
|
||||||
|
322 0.8318
|
||||||
|
323 0.8318
|
||||||
|
324 0.8511
|
||||||
|
325 0.8511
|
||||||
|
326 0.8710
|
||||||
|
327 0.8710
|
||||||
|
328 0.8710
|
||||||
|
329 0.8913
|
||||||
|
330 0.8913
|
||||||
|
331 0.8913
|
||||||
|
332 0.9120
|
||||||
|
333 0.9120
|
||||||
|
334 0.9120
|
||||||
|
335 0.9333
|
||||||
|
336 0.9333
|
||||||
|
337 0.9333
|
||||||
|
338 0.9333
|
||||||
|
339 0.9550
|
||||||
|
340 0.9550
|
||||||
|
341 0.9550
|
||||||
|
342 0.9550
|
||||||
|
343 0.9550
|
||||||
|
344 0.9772
|
||||||
|
345 0.9772
|
||||||
|
346 0.9772
|
||||||
|
347 0.9772
|
||||||
|
348 0.9772
|
||||||
|
349 0.9772
|
||||||
|
350 0.9772
|
||||||
|
351 0.9772
|
||||||
|
352 1.0000
|
||||||
|
353 1.0000
|
||||||
|
354 1.0000
|
||||||
|
355 1.0000
|
||||||
|
356 1.0000
|
||||||
|
357 1.0000
|
||||||
|
358 1.0000
|
||||||
|
359 1.0000
|
102
antenna/DB413-B.el
Normal file
102
antenna/DB413-B.el
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
0 0
|
||||||
|
-10 0.0398
|
||||||
|
-9 0.0257
|
||||||
|
-8 0.0063
|
||||||
|
-7 0.0045
|
||||||
|
-6 0.0479
|
||||||
|
-5 0.1585
|
||||||
|
-4 0.3388
|
||||||
|
-3 0.5623
|
||||||
|
-2 0.7943
|
||||||
|
-1 0.9550
|
||||||
|
0 1.0000
|
||||||
|
1 0.9333
|
||||||
|
2 0.7413
|
||||||
|
3 0.5129
|
||||||
|
4 0.2884
|
||||||
|
5 0.1175
|
||||||
|
6 0.0251
|
||||||
|
7 0.0001
|
||||||
|
8 0.0141
|
||||||
|
9 0.0363
|
||||||
|
10 0.0468
|
||||||
|
11 0.0407
|
||||||
|
12 0.0245
|
||||||
|
13 0.0095
|
||||||
|
14 0.0021
|
||||||
|
15 0.0030
|
||||||
|
16 0.0079
|
||||||
|
17 0.0123
|
||||||
|
18 0.0129
|
||||||
|
19 0.0102
|
||||||
|
20 0.0065
|
||||||
|
21 0.0035
|
||||||
|
22 0.0023
|
||||||
|
23 0.0029
|
||||||
|
24 0.0045
|
||||||
|
25 0.0060
|
||||||
|
26 0.0071
|
||||||
|
27 0.0072
|
||||||
|
28 0.0062
|
||||||
|
29 0.0044
|
||||||
|
30 0.0025
|
||||||
|
31 0.0014
|
||||||
|
32 0.0019
|
||||||
|
33 0.0039
|
||||||
|
34 0.0065
|
||||||
|
35 0.0083
|
||||||
|
36 0.0085
|
||||||
|
37 0.0066
|
||||||
|
38 0.0036
|
||||||
|
39 0.0010
|
||||||
|
40 0.0003
|
||||||
|
41 0.0020
|
||||||
|
42 0.0056
|
||||||
|
43 0.0098
|
||||||
|
44 0.0126
|
||||||
|
45 0.0129
|
||||||
|
46 0.0107
|
||||||
|
47 0.0068
|
||||||
|
48 0.0028
|
||||||
|
49 0.0004
|
||||||
|
50 0.0004
|
||||||
|
51 0.0029
|
||||||
|
52 0.0071
|
||||||
|
53 0.0112
|
||||||
|
54 0.0145
|
||||||
|
55 0.0151
|
||||||
|
56 0.0132
|
||||||
|
57 0.0095
|
||||||
|
58 0.0050
|
||||||
|
59 0.0014
|
||||||
|
60 0.0002
|
||||||
|
61 0.0024
|
||||||
|
62 0.0085
|
||||||
|
63 0.0182
|
||||||
|
64 0.0316
|
||||||
|
65 0.0457
|
||||||
|
66 0.0617
|
||||||
|
67 0.0759
|
||||||
|
68 0.0871
|
||||||
|
69 0.0977
|
||||||
|
70 0.1047
|
||||||
|
71 0.1072
|
||||||
|
72 0.1072
|
||||||
|
73 0.1023
|
||||||
|
74 0.0977
|
||||||
|
75 0.0891
|
||||||
|
76 0.0813
|
||||||
|
77 0.0708
|
||||||
|
78 0.0617
|
||||||
|
79 0.0525
|
||||||
|
80 0.0437
|
||||||
|
81 0.0347
|
||||||
|
82 0.0275
|
||||||
|
83 0.0209
|
||||||
|
84 0.0151
|
||||||
|
85 0.0105
|
||||||
|
86 0.0066
|
||||||
|
87 0.0036
|
||||||
|
88 0.0016
|
||||||
|
89 0.0004
|
||||||
|
90 0.0001
|
3
color/black.scf
Normal file
3
color/black.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 0, 0, 0
|
||||||
|
0: 0, 0, 0
|
3
color/blue.scf
Normal file
3
color/blue.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 0, 0, 255
|
||||||
|
0: 0, 0, 255
|
3
color/cyan.scf
Normal file
3
color/cyan.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 0, 255, 255
|
||||||
|
0: 0, 255, 255
|
3
color/green.scf
Normal file
3
color/green.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 0, 255, 0
|
||||||
|
0: 0, 255, 0
|
3
color/magenta.scf
Normal file
3
color/magenta.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 255, 0, 255
|
||||||
|
0: 255, 0, 255
|
16
color/rainbow.dcf
Normal file
16
color/rainbow.dcf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
+0: 255, 0, 0
|
||||||
|
-10: 255, 128, 0
|
||||||
|
-20: 255, 165, 0
|
||||||
|
-30: 255, 206, 0
|
||||||
|
-40: 255, 255, 0
|
||||||
|
-50: 184, 255, 0
|
||||||
|
-60: 0, 255, 0
|
||||||
|
-70: 0, 208, 0
|
||||||
|
-80: 0, 196, 196
|
||||||
|
-90: 0, 148, 255
|
||||||
|
-100: 80, 80, 255
|
||||||
|
-110: 0, 38, 255
|
||||||
|
-120: 142, 63, 255
|
||||||
|
-130: 196, 54, 255
|
||||||
|
-140: 255, 0, 255
|
||||||
|
-150: 255, 194, 204
|
13
color/rainbow.scf
Normal file
13
color/rainbow.scf
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
128: 255, 0, 0
|
||||||
|
118: 255, 165, 0
|
||||||
|
108: 255, 206, 0
|
||||||
|
98: 255, 255, 0
|
||||||
|
88: 184, 255, 0
|
||||||
|
78: 0, 255, 0
|
||||||
|
68: 0, 208, 0
|
||||||
|
58: 0, 196, 196
|
||||||
|
48: 0, 148, 255
|
||||||
|
38: 80, 80, 255
|
||||||
|
28: 0, 38, 255
|
||||||
|
18: 142, 63, 255
|
||||||
|
8: 140, 0, 128
|
3
color/red.scf
Normal file
3
color/red.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 255, 0, 0
|
||||||
|
0: 255, 0, 0
|
3
color/yellow.scf
Normal file
3
color/yellow.scf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
200: 255, 255, 255
|
||||||
|
59: 255, 255, 0
|
||||||
|
0: 255, 255, 0
|
12960004
data/51:52:0:1-hd.sdf
Normal file
12960004
data/51:52:0:1-hd.sdf
Normal file
File diff suppressed because it is too large
Load Diff
1440004
data/51:52:0:1.sdf
Normal file
1440004
data/51:52:0:1.sdf
Normal file
File diff suppressed because it is too large
Load Diff
3606
data/N051E000_AVE_DSM.tif.asc
Normal file
3606
data/N051E000_AVE_DSM.tif.asc
Normal file
File diff suppressed because one or more lines are too long
3606
data/N051W001_AVE_DSM.tif.asc
Normal file
3606
data/N051W001_AVE_DSM.tif.asc
Normal file
File diff suppressed because one or more lines are too long
1473
data/sk3587_50cm.asc
Normal file
1473
data/sk3587_50cm.asc
Normal file
File diff suppressed because one or more lines are too long
BIN
data/sk3587_50cm.jpg
Normal file
BIN
data/sk3587_50cm.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
11
data/test.udt
Normal file
11
data/test.udt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Put a giant 5000 foot wall in the middle of Lake Michigan near Chicago!
|
||||||
|
42.280056,-87.772222,5000
|
||||||
|
42.281056,-87.772222,5000
|
||||||
|
42.282056,-87.772222,5000
|
||||||
|
42.283056,-87.772222,5000
|
||||||
|
42.284056,-87.772222,5000
|
||||||
|
42.285056,-87.772222,5000
|
||||||
|
42.286056,-87.772222,5000
|
||||||
|
42.287056,-87.772222,5000
|
||||||
|
42.288056,-87.772222,5000
|
||||||
|
42.289056,-87.772222,5000
|
42
genkmz.sh
Executable file
42
genkmz.sh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
while read line
|
||||||
|
do
|
||||||
|
echo $line
|
||||||
|
if [[ $line == Writing* ]]
|
||||||
|
then
|
||||||
|
while IFS='"' read -ra writingline
|
||||||
|
do
|
||||||
|
# echo "writingline: ${writingline}"
|
||||||
|
filename=${writingline[1]%.*}
|
||||||
|
# echo "filename: ${filename}"
|
||||||
|
done <<< $line
|
||||||
|
fi
|
||||||
|
if [[ $line == \|* ]]
|
||||||
|
then
|
||||||
|
while IFS='|' read -ra coords
|
||||||
|
do
|
||||||
|
cat << EOF > doc.kml
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<GroundOverlay>
|
||||||
|
<name>${filename}</name>
|
||||||
|
<Icon>
|
||||||
|
<href>${filename}.png</href>
|
||||||
|
</Icon>
|
||||||
|
<LatLonBox>
|
||||||
|
<north>${coords[1]}</north>
|
||||||
|
<east>${coords[2]}</east>
|
||||||
|
<south>${coords[3]}</south>
|
||||||
|
<west>${coords[4]}</west>
|
||||||
|
</LatLonBox>
|
||||||
|
</GroundOverlay>
|
||||||
|
</kml>
|
||||||
|
EOF
|
||||||
|
done <<< $line
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
#echo "filename: ${filename}"
|
||||||
|
zip "${filename}" "${filename}.png" "doc.kml"
|
||||||
|
mv "${filename}".zip "${filename}".kmz
|
||||||
|
rm "doc.kml"
|
||||||
|
echo Generated "${filename}".kmz
|
18
runsig.sh
Executable file
18
runsig.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $# -eq 0 ]] ; then
|
||||||
|
echo Usage:
|
||||||
|
echo $0 -lat 46.4879 -lon -123.2144 -txh 60 -f 145 -erp 30 -R 80 -o outfile | ./genkmz.sh
|
||||||
|
echo The last argument must be the output file name.
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for name; do true; done
|
||||||
|
|
||||||
|
# This script should contain options common to every run on the target system.
|
||||||
|
|
||||||
|
#time ./signalserverHD -sdf /mnt/data -pm 1 -rxh 6 -te 3 -cl 5 -pe 2 -dbg $@ 2>&1
|
||||||
|
time ./signalserver -sdf /mnt/data -pm 1 -rxh 6 -te 3 -cl 5 -pe 2 -dbg $@ 2>&1
|
||||||
|
# to resize, add: -resize 7000x7000\>
|
||||||
|
convert $name.ppm -transparent white $name.png
|
77
src/Makefile
Normal file
77
src/Makefile
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CXX = g++
|
||||||
|
CFLAGS = -Wall -O3 -s -ffast-math -DCROPPING
|
||||||
|
CXXFLAGS = -Wall -O3 -s -ffast-math
|
||||||
|
LIBS = -lm -lpthread -ldl -lbz2 -lz
|
||||||
|
|
||||||
|
INSTALL_PATH = ..
|
||||||
|
VPATH = models
|
||||||
|
objects = main.o cost.o ecc33.o ericsson.o fspl.o hata.o itwom3.0.o \
|
||||||
|
los.o sui.o pel.o egli.o soil.o inputs.o outputs.o image.o \
|
||||||
|
image-ppm.o tiles.o
|
||||||
|
|
||||||
|
GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 1)
|
||||||
|
GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 2)
|
||||||
|
GCC_VER_OK := $(shell test $(GCC_MAJOR) -ge 4 && \
|
||||||
|
test $(GCC_MINOR) -ge 7 && \
|
||||||
|
echo 1)
|
||||||
|
|
||||||
|
#ifneq "$(GCC_VER_OK)" "1"
|
||||||
|
#error:
|
||||||
|
# @echo "Requires GCC version >= 4.7"
|
||||||
|
# @exit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%.o : %.cc
|
||||||
|
@echo -e " CXX\t$@"
|
||||||
|
@$ $(CXX) $(CXXFLAGS) -c $<
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
|
@echo -e " CC\t$@"
|
||||||
|
@$ $(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
signalserver: $(objects)
|
||||||
|
@echo -e " LNK\t$@"
|
||||||
|
@$(CXX) $(objects) -o $@ ${LIBS}
|
||||||
|
@echo -e " SYMLNK\tsignalserverHD -> $@"
|
||||||
|
@ln -sf $@ signalserverHD
|
||||||
|
@echo -e " SYMLNK\tsignalserverLIDAR -> $@"
|
||||||
|
@ln -sf $@ signalserverLIDAR
|
||||||
|
|
||||||
|
main.o: main.cc common.h inputs.hh outputs.hh itwom3.0.hh los.hh pel.hh \
|
||||||
|
image.hh
|
||||||
|
|
||||||
|
inputs.o: inputs.cc common.h main.hh tiles.hh
|
||||||
|
|
||||||
|
outputs.o: outputs.cc common.h main.hh inputs.hh cost.hh ecc33.hh ericsson.hh \
|
||||||
|
fspl.hh hata.hh itwom3.0.hh sui.hh image.hh
|
||||||
|
|
||||||
|
image.o: image.cc image-ppm.o image.hh image-ppm.hh
|
||||||
|
|
||||||
|
image-ppm.o: image-ppm.cc image.hh
|
||||||
|
|
||||||
|
los.o: los.cc los.hh main.hh cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
|
||||||
|
itwom3.0.hh sui.hh pel.hh egli.hh soil.hh
|
||||||
|
|
||||||
|
tiles.o: tiles.cc tiles.hh common.h
|
||||||
|
|
||||||
|
|
||||||
|
testmodels.o: testmodels.cc cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
|
||||||
|
egli.hh sui.hh itwom3.0.hh
|
||||||
|
|
||||||
|
testmodels: testmodels.o cost.o ecc33.o ericsson.o fspl.o hata.o egli.o sui.o itwom3.0.o
|
||||||
|
@echo -e " LNK\t$@"
|
||||||
|
@$(CXX) testmodels.o cost.o ecc33.o ericsson.o fspl.o hata.o egli.o \
|
||||||
|
sui.o itwom3.0.o -o $@ ${LIBS}
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(objects) signalserver signalserverHD signalserverLIDAR testmodels
|
||||||
|
|
||||||
|
all: signalserver
|
||||||
|
|
||||||
|
install: all
|
||||||
|
cp -a signalserver signalserverHD signalserverLIDAR $(INSTALL_PATH)
|
||||||
|
|
131
src/common.h
Normal file
131
src/common.h
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#ifndef _COMMON_H_
|
||||||
|
#define _COMMON_H_
|
||||||
|
|
||||||
|
#define GAMMA 2.5
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.141592653589793
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TWOPI
|
||||||
|
#define TWOPI 6.283185307179586
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HALFPI
|
||||||
|
#define HALFPI 1.570796326794896
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEG2RAD 1.74532925199e-02
|
||||||
|
#define EARTHRADIUS 20902230.97
|
||||||
|
#define METERS_PER_MILE 1609.344
|
||||||
|
#define METERS_PER_FOOT 0.3048
|
||||||
|
#define KM_PER_MILE 1.609344
|
||||||
|
#define FEET_PER_MILE 5280.0
|
||||||
|
#define FOUR_THIRDS 1.3333333333333
|
||||||
|
|
||||||
|
#define MAX(x,y)((x)>(y)?(x):(y))
|
||||||
|
|
||||||
|
struct dem {
|
||||||
|
float min_north;
|
||||||
|
float max_north;
|
||||||
|
float min_west;
|
||||||
|
float max_west;
|
||||||
|
int max_el;
|
||||||
|
int min_el;
|
||||||
|
short **data;
|
||||||
|
unsigned char **mask;
|
||||||
|
unsigned char **signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct site {
|
||||||
|
double lat;
|
||||||
|
double lon;
|
||||||
|
float alt;
|
||||||
|
char name[50];
|
||||||
|
char filename[255];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct path {
|
||||||
|
double *lat;
|
||||||
|
double *lon;
|
||||||
|
double *elevation;
|
||||||
|
double *distance;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LR {
|
||||||
|
double eps_dielect;
|
||||||
|
double sgm_conductivity;
|
||||||
|
double eno_ns_surfref;
|
||||||
|
double frq_mhz;
|
||||||
|
double conf;
|
||||||
|
double rel;
|
||||||
|
double erp;
|
||||||
|
int radio_climate;
|
||||||
|
int pol;
|
||||||
|
float antenna_pattern[361][1001];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct region {
|
||||||
|
unsigned char color[128][3];
|
||||||
|
int level[128];
|
||||||
|
int levels;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int MAXPAGES;
|
||||||
|
extern int ARRAYSIZE;
|
||||||
|
extern int IPPD;
|
||||||
|
|
||||||
|
extern double min_north;
|
||||||
|
extern double max_north;
|
||||||
|
extern double min_west;
|
||||||
|
extern double max_west;
|
||||||
|
extern int ippd;
|
||||||
|
extern int MAXRAD;
|
||||||
|
extern int mpi;
|
||||||
|
extern int max_elevation;
|
||||||
|
extern int min_elevation;
|
||||||
|
extern int contour_threshold;
|
||||||
|
extern int loops;
|
||||||
|
extern int jgets;
|
||||||
|
extern int width;
|
||||||
|
extern int height;
|
||||||
|
|
||||||
|
extern double earthradius;
|
||||||
|
extern double north;
|
||||||
|
extern double east;
|
||||||
|
extern double south;
|
||||||
|
extern double west;
|
||||||
|
extern double max_range;
|
||||||
|
extern double dpp;
|
||||||
|
extern double ppd;
|
||||||
|
extern double yppd;
|
||||||
|
extern double fzone_clearance;
|
||||||
|
extern double clutter;
|
||||||
|
extern double dBm;
|
||||||
|
extern double loss;
|
||||||
|
extern double field_strength;
|
||||||
|
extern __thread double *elev;
|
||||||
|
extern double westoffset;
|
||||||
|
extern double eastoffset;
|
||||||
|
extern double delta;
|
||||||
|
extern double cropLat;
|
||||||
|
extern double cropLon;
|
||||||
|
|
||||||
|
extern char string[];
|
||||||
|
extern char sdf_path[];
|
||||||
|
extern char gpsav;
|
||||||
|
|
||||||
|
extern unsigned char got_elevation_pattern;
|
||||||
|
extern unsigned char got_azimuth_pattern;
|
||||||
|
extern unsigned char metric;
|
||||||
|
extern unsigned char dbm;
|
||||||
|
|
||||||
|
extern struct dem *dem;
|
||||||
|
extern __thread struct path path;
|
||||||
|
extern struct LR LR;
|
||||||
|
extern struct region region;
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
|
||||||
|
#endif /* _COMMON_H_ */
|
59
src/image-ppm.cc
Normal file
59
src/image-ppm.cc
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "image.hh"
|
||||||
|
|
||||||
|
int ppm_init(image_ctx_t *ctx){
|
||||||
|
size_t buf_size;
|
||||||
|
|
||||||
|
/* Perform simple sanity checking */
|
||||||
|
if(ctx->canvas != NULL)
|
||||||
|
return EINVAL;
|
||||||
|
ctx->model = IMAGE_RGB; //Override this as we only support RGB
|
||||||
|
ctx->format = IMAGE_PPM;
|
||||||
|
ctx->extension = (char*)".ppm";
|
||||||
|
|
||||||
|
buf_size = ctx->width * ctx->height * RGB_SIZE;
|
||||||
|
|
||||||
|
/* Allocate the canvas buffer */
|
||||||
|
ctx->canvas = (uint8_t*) calloc(buf_size,sizeof(uint8_t));
|
||||||
|
ctx->next_pixel = ctx->canvas;
|
||||||
|
if(ctx->canvas == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppm_add_pixel(image_ctx_t *ctx,const uint8_t r,const uint8_t g,const uint8_t b,const uint8_t a){
|
||||||
|
register uint8_t* next;
|
||||||
|
|
||||||
|
next = ctx->next_pixel;
|
||||||
|
|
||||||
|
next[0] = r;
|
||||||
|
next[1] = g;
|
||||||
|
next[2] = b;
|
||||||
|
|
||||||
|
ctx->next_pixel += 3;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppm_get_pixel(image_ctx_t *ctx,const size_t x,const size_t y,const uint8_t *r,const uint8_t *g,const uint8_t *b,const uint8_t *a){
|
||||||
|
/* STUB */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppm_write(image_ctx_t *ctx, FILE* fd){
|
||||||
|
size_t written;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
count = ctx->width * ctx->height * RGB_SIZE;
|
||||||
|
|
||||||
|
fprintf(fd, "P6\n%zu %zu\n255\n", ctx->width, ctx->height);
|
||||||
|
written = fwrite(ctx->canvas,sizeof(uint8_t),count,fd);
|
||||||
|
if(written < count)
|
||||||
|
return EPIPE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
23
src/image-ppm.hh
Normal file
23
src/image-ppm.hh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _IMAGE_PPM_HH
|
||||||
|
#define _IMAGE_PPM_HH
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "image.hh"
|
||||||
|
|
||||||
|
int ppm_init(image_ctx_t *ctx);
|
||||||
|
int ppm_add_pixel(image_ctx_t *ctx,const uint8_t r,const uint8_t g,const uint8_t b,const uint8_t a);
|
||||||
|
int ppm_get_pixel(image_ctx_t *ctx,const size_t x,const size_t y,const uint8_t *r,const uint8_t *g,const uint8_t *b,const uint8_t *a);
|
||||||
|
int ppm_write(image_ctx_t *ctx, FILE* fd);
|
||||||
|
|
||||||
|
image_dispatch_table_t ppm_dt = {\
|
||||||
|
.init = ppm_init, \
|
||||||
|
.add_pixel = ppm_add_pixel, \
|
||||||
|
.set_pixel = NULL, \
|
||||||
|
.get_pixel = ppm_get_pixel, \
|
||||||
|
.write = ppm_write, \
|
||||||
|
.free = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
275
src/image.cc
Normal file
275
src/image.cc
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* Generic image output handling. This feature allows
|
||||||
|
* for extensible image output formats and permits for
|
||||||
|
* cleaner image rendering code in the model generation
|
||||||
|
* routines by moving all of the file-format specific
|
||||||
|
* logic to be handled here.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include "image.hh"
|
||||||
|
#include "image-ppm.hh"
|
||||||
|
|
||||||
|
int get_dt(image_dispatch_table_t *dt, int format);
|
||||||
|
int load_library(image_dispatch_table_t *dt);
|
||||||
|
|
||||||
|
#define DISPATCH_TABLE(ctx) ((image_dispatch_table_t*)(ctx)->_dt)
|
||||||
|
|
||||||
|
static int default_format = IMAGE_PPM;
|
||||||
|
char *dynamic_backend = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_set_format
|
||||||
|
* Changes the default format for the next
|
||||||
|
* uninitialized image canvas
|
||||||
|
*/
|
||||||
|
int image_set_format(int format){
|
||||||
|
if(format <= IMAGE_DEFAULT || format >= IMAGE_FORMAT_MAX)
|
||||||
|
return EINVAL;
|
||||||
|
default_format = format;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_init
|
||||||
|
* Initialize an image context. Must be called
|
||||||
|
* before attempting to write any image data
|
||||||
|
*/
|
||||||
|
int image_init(image_ctx_t *ctx, \
|
||||||
|
const size_t width, \
|
||||||
|
const size_t height, \
|
||||||
|
const int model, \
|
||||||
|
const int format) {
|
||||||
|
|
||||||
|
int success = 0;
|
||||||
|
image_dispatch_table_t *dt;
|
||||||
|
|
||||||
|
/* Perform some sanity checking on provided arguments */
|
||||||
|
if(ctx == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
if(width == 0 || height == 0)
|
||||||
|
return EINVAL;
|
||||||
|
if(model < 0 || model > IMAGE_MODEL_MAX)
|
||||||
|
return EINVAL;
|
||||||
|
if(format >= IMAGE_FORMAT_MAX || (format == IMAGE_LIBRARY && dynamic_backend == NULL))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
memset(ctx,0x00,sizeof(image_ctx_t));
|
||||||
|
|
||||||
|
/* Assign the initialize values to the processing context */
|
||||||
|
ctx->width = width;
|
||||||
|
ctx->height = height;
|
||||||
|
ctx->model = model;
|
||||||
|
if(format == IMAGE_DEFAULT)
|
||||||
|
ctx->format = default_format;
|
||||||
|
else
|
||||||
|
ctx->format = format;
|
||||||
|
|
||||||
|
/* Get the dispatch table for this image format */
|
||||||
|
dt = (image_dispatch_table_t *) calloc(1,sizeof(image_dispatch_table_t));
|
||||||
|
if(dt == NULL){
|
||||||
|
fprintf(stderr,"Error allocating dispatch table\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
success = get_dt(dt,ctx->format);
|
||||||
|
if(success != 0){
|
||||||
|
fprintf(stderr,"Error locating dispatch table\n");
|
||||||
|
free(dt);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
ctx->_dt = (void*)dt;
|
||||||
|
|
||||||
|
/* Call the format-specific initialization function */
|
||||||
|
success = dt->init(ctx);
|
||||||
|
if(success != 0){
|
||||||
|
fprintf(stderr,"Error initializing image context\n");
|
||||||
|
free(dt);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->initialized = 1;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* image_add_pixel, image_set_pixel, image_get_pixel, image_write, image_free
|
||||||
|
* Various setters ad getters for assigning pixel data. image_write
|
||||||
|
* takes an open file handle and writes image data to it.
|
||||||
|
* These functions simply wrap the underlying format-specific functions
|
||||||
|
*/
|
||||||
|
int image_add_pixel(image_ctx_t *ctx, const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a){
|
||||||
|
if(ctx->initialized != 1) return EINVAL;
|
||||||
|
return DISPATCH_TABLE(ctx)->add_pixel(ctx,r,g,b,a);
|
||||||
|
}
|
||||||
|
int image_set_pixel(image_ctx_t *ctx, const size_t x, const size_t y, const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a){
|
||||||
|
size_t block_size;
|
||||||
|
if(ctx->initialized != 1) return EINVAL;
|
||||||
|
/* Image format handlers have the option to specify a _set_pixel handler */
|
||||||
|
if(DISPATCH_TABLE(ctx)->set_pixel != NULL){
|
||||||
|
return DISPATCH_TABLE(ctx)->set_pixel(ctx,x,y,r,g,b,a);
|
||||||
|
}
|
||||||
|
block_size = ctx->model == IMAGE_RGB ? RGB_SIZE : RGBA_SIZE;
|
||||||
|
ctx->next_pixel = ctx->canvas + PIXEL_OFFSET(x,y,ctx->width,block_size);
|
||||||
|
return DISPATCH_TABLE(ctx)->add_pixel(ctx,r,g,b,a);
|
||||||
|
}
|
||||||
|
int image_get_pixel(image_ctx_t *ctx, const size_t x, const size_t y, const uint8_t *r, const uint8_t *g, const uint8_t *b, const uint8_t *a){
|
||||||
|
if(ctx->initialized != 1) return EINVAL;
|
||||||
|
if(DISPATCH_TABLE(ctx)->get_pixel != NULL)
|
||||||
|
return DISPATCH_TABLE(ctx)->get_pixel(ctx,x,y,r,g,b,a);
|
||||||
|
return ENOSYS;
|
||||||
|
}
|
||||||
|
int image_write(image_ctx_t *ctx, FILE *fd){
|
||||||
|
if(ctx->initialized != 1) return EINVAL;
|
||||||
|
return DISPATCH_TABLE(ctx)->write(ctx,fd);
|
||||||
|
}
|
||||||
|
void image_free(image_ctx_t *ctx){
|
||||||
|
if(ctx->initialized != 1) return;
|
||||||
|
if(DISPATCH_TABLE(ctx)->free != NULL){
|
||||||
|
DISPATCH_TABLE(ctx)->free(ctx);
|
||||||
|
}
|
||||||
|
if(ctx->canvas != NULL) free(ctx->canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_get_filename
|
||||||
|
* Creates an appropriate file name using data supplied
|
||||||
|
* by the user. If the extension is already correct, return
|
||||||
|
* that; if not append if there is space
|
||||||
|
*/
|
||||||
|
int image_get_filename(image_ctx_t *ctx, char *out, size_t len_out, char *in){
|
||||||
|
size_t len_src;
|
||||||
|
size_t len_ext;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
if(ctx->initialized != 1)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
/* Get various lengths */
|
||||||
|
len_src = strlen(in);
|
||||||
|
len_ext = strlen(ctx->extension);
|
||||||
|
|
||||||
|
if(len_src == 0){
|
||||||
|
in = (char*)"output";
|
||||||
|
len_src = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len_src > len_ext && strcmp(in+len_src-len_ext,ctx->extension) == 0){
|
||||||
|
/* Already has correct extension and fits in buffer */
|
||||||
|
if(len_src < len_out)
|
||||||
|
strncpy(in,out,len_out);
|
||||||
|
else
|
||||||
|
success = ENOMEM;
|
||||||
|
}else if(len_src > len_ext){
|
||||||
|
/* Doesn't have correct extension and fits */
|
||||||
|
if(len_src + len_ext < len_out){
|
||||||
|
strncpy(out,in,len_out);
|
||||||
|
strncat(out,ctx->extension,len_out);
|
||||||
|
}else
|
||||||
|
success = ENOMEM;
|
||||||
|
}else{
|
||||||
|
/* The input buffer plus an extension cannot fit in the output buffer */
|
||||||
|
fprintf(stderr,"Error building image output filename\n");
|
||||||
|
success = ENOMEM;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_dt
|
||||||
|
* Load the dispatch table for the specified image
|
||||||
|
* format. Currently only pixmap supported.
|
||||||
|
*/
|
||||||
|
int get_dt(image_dispatch_table_t *dt, int format){
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
memset((void*)dt,0x00,sizeof(image_dispatch_table_t));
|
||||||
|
switch(format){
|
||||||
|
case IMAGE_PPM:
|
||||||
|
*dt = ppm_dt;
|
||||||
|
break;
|
||||||
|
case IMAGE_LIBRARY:
|
||||||
|
success = load_library(dt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
success = EINVAL;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ==WARNING==: Here be dragons!
|
||||||
|
* Experimantal features beyond this point.
|
||||||
|
* Only use if you are sure you know what you
|
||||||
|
* are doing!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* image_set_library
|
||||||
|
* Set the library to use for generating images
|
||||||
|
*/
|
||||||
|
int image_set_library(char *library){
|
||||||
|
char *libname;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
length = strlen(library) + 1;
|
||||||
|
libname = (char*)calloc(length,sizeof(char));
|
||||||
|
if(libname == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
strncpy(libname,library,length);
|
||||||
|
|
||||||
|
dynamic_backend = libname;
|
||||||
|
default_format = IMAGE_LIBRARY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* image_get_library
|
||||||
|
* Returns the current saved image rendering
|
||||||
|
* library
|
||||||
|
*/
|
||||||
|
char* image_get_library(){
|
||||||
|
return dynamic_backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load_library
|
||||||
|
* External image processing: experimental feature
|
||||||
|
* Load an external library to perform image processing
|
||||||
|
* It must be a custom compatible library
|
||||||
|
*/
|
||||||
|
int load_library(image_dispatch_table_t *dt){
|
||||||
|
void *hndl;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
/* Validate object file */
|
||||||
|
if(dynamic_backend == NULL || strlen(dynamic_backend) == 0){
|
||||||
|
fprintf(stderr,"Custom image processor requested without specification\n");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load shared object and locate required exports */
|
||||||
|
hndl = dlopen(dynamic_backend,RTLD_LAZY);
|
||||||
|
if(hndl == NULL){
|
||||||
|
fprintf(stderr,"Error loading shared object\n");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
/* Perform symbol lookup */
|
||||||
|
if((dt->init = (_init*)dlsym(hndl,"lib_init")) == NULL ||
|
||||||
|
(dt->add_pixel = (_add_pixel*)dlsym(hndl,"lib_add_pixel")) == NULL ||
|
||||||
|
(dt->write = (_write*)dlsym(hndl,"lib_write")) == NULL){
|
||||||
|
fprintf(stderr,"Invalid image processing module specified\n\t%s",dlerror());
|
||||||
|
success = EINVAL;
|
||||||
|
(void) dlclose(hndl);
|
||||||
|
}
|
||||||
|
/* Lookup optional symbols, these can return NULL */
|
||||||
|
if(success == 0){
|
||||||
|
dt->get_pixel = (_get_pixel*)dlsym(hndl,"lib_get_pixel");
|
||||||
|
dt->set_pixel = (_set_pixel*)dlsym(hndl,"lib_set_pixel");
|
||||||
|
dt->free = (_free*)dlsym(hndl,"lib_free");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
63
src/image.hh
Normal file
63
src/image.hh
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef _IMAGE_HH_
|
||||||
|
#define _IMAGE_HH_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define RGB_SIZE 3
|
||||||
|
#define RGBA_SIZE 4
|
||||||
|
|
||||||
|
enum _image_format{ IMAGE_DEFAULT = 0, \
|
||||||
|
IMAGE_PPM, \
|
||||||
|
IMAGE_LIBRARY, \
|
||||||
|
IMAGE_FORMAT_MAX \
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _image_model{ IMAGE_RGB, \
|
||||||
|
IMAGE_RGBA, \
|
||||||
|
IMAGE_MODEL_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _image_ctx{
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
int model;
|
||||||
|
int format;
|
||||||
|
uint8_t *canvas;
|
||||||
|
uint8_t *next_pixel;
|
||||||
|
uint32_t initialized;
|
||||||
|
char *extension;
|
||||||
|
void *_dt;
|
||||||
|
} image_ctx_t, *pimage_ctx_t;
|
||||||
|
|
||||||
|
typedef int _init(image_ctx_t*);
|
||||||
|
typedef int _add_pixel(image_ctx_t*,const uint8_t,const uint8_t,const uint8_t,const uint8_t);
|
||||||
|
typedef int _set_pixel(image_ctx_t*,const size_t,const size_t,const uint8_t,const uint8_t,const uint8_t,const uint8_t);
|
||||||
|
typedef int _get_pixel(image_ctx_t*,const size_t,const size_t,const uint8_t*,const uint8_t*,const uint8_t*,const uint8_t*);
|
||||||
|
typedef int _write(image_ctx_t*,FILE*);
|
||||||
|
typedef void _free(image_ctx_t*);
|
||||||
|
|
||||||
|
typedef struct _image_dispatch_table{
|
||||||
|
_init *init;
|
||||||
|
_add_pixel *add_pixel;
|
||||||
|
_set_pixel *set_pixel;
|
||||||
|
_get_pixel *get_pixel;
|
||||||
|
_write *write;
|
||||||
|
_free *free;
|
||||||
|
} image_dispatch_table_t;
|
||||||
|
|
||||||
|
int image_set_format(int);
|
||||||
|
int image_init(image_ctx_t*, const size_t, const size_t, const int, const int);
|
||||||
|
int image_add_pixel(image_ctx_t* ctx, const uint8_t, const uint8_t, const uint8_t, const uint8_t);
|
||||||
|
int image_set_pixel(image_ctx_t* ctx, const size_t, const size_t, const uint8_t, const uint8_t, const uint8_t, const uint8_t);
|
||||||
|
int image_get_pixel(image_ctx_t* ctx,const size_t,const size_t, uint8_t const*, uint8_t const*, uint8_t const*, uint8_t const*);
|
||||||
|
int image_get_filename(image_ctx_t*, char*, size_t, char*);
|
||||||
|
int image_write(image_ctx_t*, FILE*);
|
||||||
|
void image_free(image_ctx_t*);
|
||||||
|
int image_set_library(char*);
|
||||||
|
|
||||||
|
#define ADD_PIXEL(ctx,r,g,b) image_add_pixel((ctx),(r),(g),(b),0xff)
|
||||||
|
#define ADD_PIXELA(ctx,r,g,b,a) image_add_pixel((ctx),(r),(g),(b),(a))
|
||||||
|
|
||||||
|
#define PIXEL_OFFSET(x,y,width,pixel_size) (((x) * (pixel_size)) + ((width) * (pixel_size) * (y)))
|
||||||
|
|
||||||
|
#endif
|
2514
src/inputs.cc
Normal file
2514
src/inputs.cc
Normal file
File diff suppressed because it is too large
Load Diff
29
src/inputs.hh
Normal file
29
src/inputs.hh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _INPUTS_HH_
|
||||||
|
#define _INPUTS_HH_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
extern char scf_file[255];
|
||||||
|
|
||||||
|
/* Resample input tiles to new resolution */
|
||||||
|
int resample_data(int scaling_factor);
|
||||||
|
int resize_data(int resolution);
|
||||||
|
|
||||||
|
int LoadSDF_SDF(char *name, int winfiles);
|
||||||
|
char *BZfgets(char *output, BZFILE *bzfd, unsigned length);
|
||||||
|
int LoadSDF_GZ(char *name);
|
||||||
|
char *GZfgets(char *output, gzFile gzfd, unsigned length);
|
||||||
|
int LoadSDF_BZ(char *name);
|
||||||
|
int LoadSDF(char *name, int winfiles);
|
||||||
|
int LoadPAT(char *az_filename, char *el_filename);
|
||||||
|
int LoadSignalColors(struct site xmtr);
|
||||||
|
int LoadLossColors(struct site xmtr);
|
||||||
|
int LoadDBMColors(struct site xmtr);
|
||||||
|
int LoadTopoData(double max_lon, double min_lon, double max_lat, double min_lat);
|
||||||
|
int LoadUDT(char *filename);
|
||||||
|
int loadLIDAR(char *filename, int resample);
|
||||||
|
int loadClutter(char *filename, double radius, struct site tx);
|
||||||
|
int averageHeight(int h, int w, int x, int y);
|
||||||
|
static const char AZ_FILE_SUFFIX[] = ".az";
|
||||||
|
static const char EL_FILE_SUFFIX[] = ".el";
|
||||||
|
|
||||||
|
#endif /* _INPUTS_HH_ */
|
2057
src/main.cc
Normal file
2057
src/main.cc
Normal file
File diff suppressed because it is too large
Load Diff
33
src/main.hh
Normal file
33
src/main.hh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef _MAIN_HH_
|
||||||
|
#define _MAIN_HH_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int ReduceAngle(double angle);
|
||||||
|
double LonDiff(double lon1, double lon2);
|
||||||
|
void *dec2dms(double decimal, char *string);
|
||||||
|
int PutMask(double lat, double lon, int value);
|
||||||
|
int OrMask(double lat, double lon, int value);
|
||||||
|
int GetMask(double lat, double lon);
|
||||||
|
void PutSignal(double lat, double lon, unsigned char signal);
|
||||||
|
unsigned char GetSignal(double lat, double lon);
|
||||||
|
double GetElevation(struct site location);
|
||||||
|
int AddElevation(double lat, double lon, double height, int size);
|
||||||
|
double Distance(struct site site1, struct site site2);
|
||||||
|
double Azimuth(struct site source, struct site destination);
|
||||||
|
double ElevationAngle(struct site source, struct site destination);
|
||||||
|
void ReadPath(struct site source, struct site destination);
|
||||||
|
double ElevationAngle2(struct site source, struct site destination, double er);
|
||||||
|
double ReadBearing(char *input);
|
||||||
|
void ObstructionAnalysis(struct site xmtr, struct site rcvr, double f, FILE *outfile);
|
||||||
|
void free_elev(void);
|
||||||
|
void free_path(void);
|
||||||
|
void free_dem(void);
|
||||||
|
void alloc_elev(void);
|
||||||
|
void alloc_path(void);
|
||||||
|
void alloc_dem(void);
|
||||||
|
void do_allocs(void);
|
||||||
|
|
||||||
|
#endif /* _MAIN_HH_ */
|
9
src/models/README
Normal file
9
src/models/README
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Whilst every effort has been made to ensure the accuracy of the models, their
|
||||||
|
accuracy is not guaranteed.
|
||||||
|
|
||||||
|
Finding a reputable paper to source these models from took a while. There was
|
||||||
|
lots of bad copy-paste out there. A good paper:
|
||||||
|
|
||||||
|
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||||
|
|
||||||
|
Plane earth loss model taken from "Antennas and Propagation for Wireless systems" by Simon Saunders
|
61
src/models/cost.cc
Normal file
61
src/models/cost.cc
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* COST231-HATA MODEL for Signal Server by Alex Farrant *
|
||||||
|
* 30 December 2013i *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
COST231 extension to HATA model
|
||||||
|
Frequency 1500 to 2000MHz
|
||||||
|
TxH = Base station height 30 to 200m
|
||||||
|
RxH = Mobile station height 1 to 10m
|
||||||
|
Distance 1-20km
|
||||||
|
modes 1 = URBAN, 2 = SUBURBAN, 3 = OPEN
|
||||||
|
http://morse.colorado.edu/~tlen5510/text/classwebch3.html
|
||||||
|
*/
|
||||||
|
/* if (f < 150 || f > 2000) {
|
||||||
|
fprintf
|
||||||
|
(stderr,"Error: COST231 Hata model frequency range 150-2000MHz\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
int C = 3; // 3dB for Urban
|
||||||
|
float lRxH = log10(11.75 * RxH);
|
||||||
|
float C_H = 3.2 * (lRxH * lRxH) - 4.97; // Large city (conservative)
|
||||||
|
int c0 = 69.55;
|
||||||
|
int cf = 26.16;
|
||||||
|
if (f > 1500) {
|
||||||
|
c0 = 46.3;
|
||||||
|
cf = 33.9;
|
||||||
|
}
|
||||||
|
if (mode == 2) {
|
||||||
|
C = 0; // Medium city (average)
|
||||||
|
lRxH = log10(1.54 * RxH);
|
||||||
|
C_H = 8.29 * (lRxH * lRxH) - 1.1;
|
||||||
|
}
|
||||||
|
if (mode == 3) {
|
||||||
|
C = -3; // Small city (Optimistic)
|
||||||
|
C_H = (1.1 * log10(f) - 0.7) * RxH - (1.56 * log10(f)) + 0.8;
|
||||||
|
}
|
||||||
|
float logf = log10(f);
|
||||||
|
double dbloss =
|
||||||
|
c0 + (cf * logf) - (13.82 * log10(TxH)) - C_H + (44.9 -
|
||||||
|
6.55 *
|
||||||
|
log10(TxH)) *
|
||||||
|
log10(d) + C;
|
||||||
|
return dbloss;
|
||||||
|
}
|
6
src/models/cost.hh
Normal file
6
src/models/cost.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _COST_HH_
|
||||||
|
#define _COST_HH_
|
||||||
|
|
||||||
|
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
|
||||||
|
#endif /* _COST_HH_ */
|
33
src/models/ecc33.cc
Normal file
33
src/models/ecc33.cc
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Sanity check as this model operates within limited Txh/Rxh bounds
|
||||||
|
if(TxH-RxH<0){
|
||||||
|
RxH=RxH/(d*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (f < 700 || f > 3500) {
|
||||||
|
fprintf(stderr,"Error: ECC33 model frequency range 700-3500MHz\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// MHz to GHz
|
||||||
|
f = f / 1000;
|
||||||
|
|
||||||
|
double Gr = 0.759 * RxH - 1.862; // Big city with tall buildings (1)
|
||||||
|
// PL = Afs + Abm - Gb - Gr
|
||||||
|
double Afs = 92.4 + 20 * log10(d) + 20 * log10(f);
|
||||||
|
double Abm =
|
||||||
|
20.41 + 9.83 * log10(d) + 7.894 * log10(f) +
|
||||||
|
9.56 * (log10(f) * log10(f));
|
||||||
|
double Gb = log10(TxH / 200) * (13.958 + 5.8 * (log10(d) * log10(d)));
|
||||||
|
if (mode > 1) { // Medium city (Europe)
|
||||||
|
Gr = (42.57 + 13.7 * log10(f)) * (log10(RxH) - 0.585);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Afs + Abm - Gb - Gr;
|
||||||
|
}
|
6
src/models/ecc33.hh
Normal file
6
src/models/ecc33.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _ECC33_HH_
|
||||||
|
#define _ECC33_HH_
|
||||||
|
|
||||||
|
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
|
||||||
|
#endif /* _ECC33_HH_ */
|
83
src/models/egli.cc
Normal file
83
src/models/egli.cc
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Egli VHF/UHF model for Signal Server by G6DTX *
|
||||||
|
* April 2017 *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License v3 *
|
||||||
|
* for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
|
||||||
|
Frequency 30 to 1000MHz
|
||||||
|
h1 = 1m and above
|
||||||
|
h2 = 1m and above
|
||||||
|
Distance 1 to 50km
|
||||||
|
|
||||||
|
http://people.seas.harvard.edu/~jones/es151/prop_models/propagation.html#pel
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
//static float fcmin = 30.0;
|
||||||
|
//static float fcmax = 1000.0;
|
||||||
|
//static float dmin = 1.0;
|
||||||
|
//static float dmax = 50.0;
|
||||||
|
//static float h1min = 1.0;
|
||||||
|
//static float h2min = 1.0;
|
||||||
|
|
||||||
|
static __inline float _10log10f(float x)
|
||||||
|
{
|
||||||
|
return(4.342944f*logf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
double EgliPathLoss(float f, float h1, float h2, float d)
|
||||||
|
{
|
||||||
|
double Lp50 = NAN;
|
||||||
|
float C1, C2;
|
||||||
|
|
||||||
|
/* if ((f >= fcmin) && (f <= fcmax) &&
|
||||||
|
(h1 >= h1min) && (h2 >= h2min))
|
||||||
|
{*/
|
||||||
|
if (h1 > 10.0 && h2 > 10.0)
|
||||||
|
{
|
||||||
|
Lp50 = 85.9;
|
||||||
|
C1 = 2.0;
|
||||||
|
C2 = 2.0;
|
||||||
|
}
|
||||||
|
else if (h1 > 10.0)
|
||||||
|
{
|
||||||
|
Lp50 = 76.3;
|
||||||
|
C1 = 2.0;
|
||||||
|
C2 = 1.0;
|
||||||
|
}
|
||||||
|
else if (h2 > 10.0)
|
||||||
|
{
|
||||||
|
Lp50 = 76.3;
|
||||||
|
C1 = 1.0;
|
||||||
|
C2 = 2.0;
|
||||||
|
}
|
||||||
|
else // both antenna heights below 10 metres
|
||||||
|
{
|
||||||
|
Lp50 = 66.7;
|
||||||
|
C1 = 1.0;
|
||||||
|
C2 = 1.0;
|
||||||
|
} // end if
|
||||||
|
|
||||||
|
Lp50 += 4.0f*_10log10f(d) + 2.0f*_10log10f(f) - C1*_10log10f(h1) - C2*_10log10f(h2);
|
||||||
|
/*}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Parameter error: Egli path loss model f=%6.2f h1=%6.2f h2=%6.2f d=%6.2f\n", f, h1, h2, d);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return(Lp50);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
6
src/models/egli.hh
Normal file
6
src/models/egli.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _EGLI_HH_
|
||||||
|
#define _EGLI_HH_
|
||||||
|
|
||||||
|
double EgliPathLoss(float f, float h1, float h2, float d);
|
||||||
|
|
||||||
|
#endif /* _EGLI_HH_ */
|
31
src/models/ericsson.cc
Normal file
31
src/models/ericsson.cc
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
AKA Ericsson 9999 model
|
||||||
|
*/
|
||||||
|
// Urban
|
||||||
|
double a0 = 36.2, a1 = 30.2, a2 = -12, a3 = 0.1;
|
||||||
|
|
||||||
|
/* if (f < 150 || f > 1900) {
|
||||||
|
fprintf
|
||||||
|
(stderr,"Error: Ericsson9999 model frequency range 150-1900MHz\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (mode == 2) { // Suburban / Med loss
|
||||||
|
a0 = 43.2;
|
||||||
|
a1 = 68.93;
|
||||||
|
}
|
||||||
|
if (mode == 1) { // Rural
|
||||||
|
a0 = 45.95;
|
||||||
|
a1 = 100.6;
|
||||||
|
}
|
||||||
|
double g1 = 3.2 * (log10(11.75 * RxH) * log10(11.75 * RxH));
|
||||||
|
double g2 = 44.49 * log10(f) - 4.78 * (log10(f) * log10(f));
|
||||||
|
|
||||||
|
return a0 + a1 * log10(d) + a2 * log10(TxH) + a3 * log10(TxH) * log10(d) - g1 + g2;
|
||||||
|
}
|
6
src/models/ericsson.hh
Normal file
6
src/models/ericsson.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _ERICSSON_HH_
|
||||||
|
#define _ERICSSON_HH_
|
||||||
|
|
||||||
|
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
|
||||||
|
#endif /* _ERICSSON_HH_ */
|
33
src/models/fspl.cc
Normal file
33
src/models/fspl.cc
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* ITU-R P.525 Free Space Path Loss model for Signal Server by Alex Farrant *
|
||||||
|
* 15 January 2014 *
|
||||||
|
* optimised G6DTX April 2017 *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
*
|
||||||
|
* https://www.itu.int/rec/R-REC-P.525/en
|
||||||
|
* Free Space Path Loss model
|
||||||
|
* Frequency: Any
|
||||||
|
* Distance: Any
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// use call with log/ln as this may be faster
|
||||||
|
// use constant of value 20.0/log(10.0)
|
||||||
|
static __inline float _20log10f(float x)
|
||||||
|
{
|
||||||
|
return(8.685889f*logf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
double FSPLpathLoss(float f, float d)
|
||||||
|
{
|
||||||
|
return(32.44 + _20log10f(f) + _20log10f(d));
|
||||||
|
}
|
6
src/models/fspl.hh
Normal file
6
src/models/fspl.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _FSPL_HH_
|
||||||
|
#define _FSPL_HH_
|
||||||
|
|
||||||
|
double FSPLpathLoss(float f, float d);
|
||||||
|
|
||||||
|
#endif /* _FSPL_HH_ */
|
58
src/models/hata.cc
Normal file
58
src/models/hata.cc
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* HATA MODEL for Signal Server by Alex Farrant *
|
||||||
|
* 30 December 2013 *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double HATApathLoss(float f, float h_B, float h_M, float d, int mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
HATA URBAN model for cellular planning
|
||||||
|
Frequency (MHz) 150 to 1500MHz
|
||||||
|
Base station height 30-200m
|
||||||
|
Mobile station height 1-10m
|
||||||
|
Distance 1-20km
|
||||||
|
|
||||||
|
mode 1 = URBAN
|
||||||
|
mode 2 = SUBURBAN
|
||||||
|
mode 3 = OPEN
|
||||||
|
*/
|
||||||
|
float lh_M;
|
||||||
|
float C_H;
|
||||||
|
float logf = log10(f);
|
||||||
|
|
||||||
|
if(f<200){
|
||||||
|
lh_M = log10(1.54 * h_M);
|
||||||
|
C_H = 8.29 * (lh_M * lh_M) - 1.1;
|
||||||
|
}else{
|
||||||
|
lh_M = log10(11.75 * h_M);
|
||||||
|
C_H = 3.2 * (lh_M * lh_M) - 4.97;
|
||||||
|
}
|
||||||
|
|
||||||
|
float L_u = 69.55 + 26.16 * logf - 13.82 * log10(h_B) - C_H + (44.9 - 6.55 * log10(h_B)) * log10(d);
|
||||||
|
|
||||||
|
if (!mode || mode == 1) {
|
||||||
|
return L_u; //URBAN
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 2) { //SUBURBAN
|
||||||
|
float logf_28 = log10(f / 28);
|
||||||
|
return L_u - 2 * logf_28 * logf_28 - 5.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 3) { //OPEN
|
||||||
|
return L_u - 4.78 * logf * logf + 18.33 * logf - 40.94;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
src/models/hata.hh
Normal file
6
src/models/hata.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _HATA_HH_
|
||||||
|
#define _HATA_HH_
|
||||||
|
|
||||||
|
double HATApathLoss(float f, float h_B, float h_M, float d, int mode);
|
||||||
|
|
||||||
|
#endif /* _HATA_HH_ */
|
1574
src/models/itm.cc
Normal file
1574
src/models/itm.cc
Normal file
File diff suppressed because it is too large
Load Diff
2964
src/models/itwom3.0.cc
Normal file
2964
src/models/itwom3.0.cc
Normal file
File diff suppressed because it is too large
Load Diff
14
src/models/itwom3.0.hh
Normal file
14
src/models/itwom3.0.hh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _ITWOM30_HH_
|
||||||
|
#define _ITWOM30_HH_
|
||||||
|
|
||||||
|
void point_to_point_ITM(double tht_m, double rht_m, double eps_dielect,
|
||||||
|
double sgm_conductivity, double eno_ns_surfref,
|
||||||
|
double frq_mhz, int radio_climate, int pol,
|
||||||
|
double conf, double rel, double &dbloss, char *strmode,
|
||||||
|
int &errnum);
|
||||||
|
void point_to_point(double tht_m, double rht_m, double eps_dielect,
|
||||||
|
double sgm_conductivity, double eno_ns_surfref,
|
||||||
|
double frq_mhz, int radio_climate, int pol, double conf,
|
||||||
|
double rel, double &dbloss, char *strmode, int &errnum);
|
||||||
|
|
||||||
|
#endif /* _ITWOM30_HH_ */
|
948
src/models/los.cc
Normal file
948
src/models/los.cc
Normal file
@@ -0,0 +1,948 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "../main.hh"
|
||||||
|
#include "los.hh"
|
||||||
|
#include "cost.hh"
|
||||||
|
#include "ecc33.hh"
|
||||||
|
#include "ericsson.hh"
|
||||||
|
#include "fspl.hh"
|
||||||
|
#include "hata.hh"
|
||||||
|
#include "itwom3.0.hh"
|
||||||
|
#include "sui.hh"
|
||||||
|
#include "pel.hh"
|
||||||
|
#include "egli.hh"
|
||||||
|
#include "soil.hh"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define NUM_SECTIONS 4
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
pthread_t threads[NUM_SECTIONS];
|
||||||
|
unsigned int thread_count = 0;
|
||||||
|
pthread_mutex_t maskMutex;
|
||||||
|
bool ***processed;
|
||||||
|
bool has_init_processed = false;
|
||||||
|
|
||||||
|
struct propagationRange {
|
||||||
|
double min_west, max_west, min_north, max_north;
|
||||||
|
double altitude;
|
||||||
|
bool eastwest, los, use_threads;
|
||||||
|
site source;
|
||||||
|
unsigned char mask_value;
|
||||||
|
FILE *fd;
|
||||||
|
int propmodel, knifeedge, pmenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
void* rangePropagation(void *parameters)
|
||||||
|
{
|
||||||
|
propagationRange *v = (propagationRange*)parameters;
|
||||||
|
if(v->use_threads) {
|
||||||
|
alloc_elev();
|
||||||
|
alloc_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
double minwest = dpp + (double)v->min_west;
|
||||||
|
double lon = v->eastwest ? minwest : v->min_west;
|
||||||
|
double lat = v->min_north;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (lon >= 360.0)
|
||||||
|
lon -= 360.0;
|
||||||
|
|
||||||
|
site edge;
|
||||||
|
edge.lat = lat;
|
||||||
|
edge.lon = lon;
|
||||||
|
edge.alt = v->altitude;
|
||||||
|
|
||||||
|
if(v->los)
|
||||||
|
PlotLOSPath(v->source, edge, v->mask_value, v->fd);
|
||||||
|
else
|
||||||
|
PlotPropPath(v->source, edge, v->mask_value, v->fd, v->propmodel,
|
||||||
|
v->knifeedge, v->pmenv);
|
||||||
|
|
||||||
|
++y;
|
||||||
|
if(v->eastwest)
|
||||||
|
lon = minwest + (dpp * (double)y);
|
||||||
|
else
|
||||||
|
lat = (double)v->min_north + (dpp * (double)y);
|
||||||
|
|
||||||
|
|
||||||
|
} while ( v->eastwest
|
||||||
|
? (LonDiff(lon, (double)v->max_west) <= 0.0)
|
||||||
|
: (lat < (double)v->max_north) );
|
||||||
|
|
||||||
|
if(v->use_threads) {
|
||||||
|
free_elev();
|
||||||
|
free_path();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_processed()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
processed = new bool **[MAXPAGES];
|
||||||
|
for (i = 0; i < MAXPAGES; i++) {
|
||||||
|
processed[i] = new bool *[ippd];
|
||||||
|
for (x = 0; x < ippd; x++)
|
||||||
|
processed[i][x] = new bool [ippd];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPAGES; i++) {
|
||||||
|
for (x = 0; x < ippd; x++) {
|
||||||
|
for (y = 0; y < ippd; y++)
|
||||||
|
processed[i][x][y] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has_init_processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool can_process(double lat, double lon)
|
||||||
|
{
|
||||||
|
/* Lines, text, markings, and coverage areas are stored in a
|
||||||
|
mask that is combined with topology data when topographic
|
||||||
|
maps are generated by ss. This function sets bits in
|
||||||
|
the mask based on the latitude and longitude of the area
|
||||||
|
pointed to. */
|
||||||
|
|
||||||
|
int x, y, indx;
|
||||||
|
char found;
|
||||||
|
bool rtn = false;
|
||||||
|
|
||||||
|
for (indx = 0, found = 0; indx < MAXPAGES && found == 0;) {
|
||||||
|
x = (int)rint(ppd * (lat - dem[indx].min_north));
|
||||||
|
y = mpi - (int)rint(yppd * (LonDiff(dem[indx].max_west, lon)));
|
||||||
|
|
||||||
|
if (x >= 0 && x <= mpi && y >= 0 && y <= mpi)
|
||||||
|
found = 1;
|
||||||
|
else
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
/* As long as we only set this without resetting it we can
|
||||||
|
check outside a mutex first without worrying about race
|
||||||
|
conditions. But we must lock the mutex before updating the
|
||||||
|
value. */
|
||||||
|
|
||||||
|
if(!processed[indx][x][y]) {
|
||||||
|
pthread_mutex_lock(&maskMutex);
|
||||||
|
|
||||||
|
if(!processed[indx][x][y]) {
|
||||||
|
rtn = true;
|
||||||
|
processed[indx][x][y] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock (&maskMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginThread(void *arg)
|
||||||
|
{
|
||||||
|
if(!has_init_processed)
|
||||||
|
init_processed();
|
||||||
|
|
||||||
|
int rc = pthread_create(&threads[thread_count], NULL, rangePropagation, arg);
|
||||||
|
if (rc)
|
||||||
|
fprintf(stderr,"ERROR; return code from pthread_create() is %d\n", rc);
|
||||||
|
else
|
||||||
|
++thread_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishThreads()
|
||||||
|
{
|
||||||
|
void* status;
|
||||||
|
for(unsigned int i=0; i<thread_count; i++) {
|
||||||
|
int rc = pthread_join(threads[i], &status);
|
||||||
|
if (rc)
|
||||||
|
fprintf(stderr,"ERROR; return code from pthread_join() is %d\n", rc);
|
||||||
|
}
|
||||||
|
thread_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Acute Angle from Rx point to an obstacle of height (opp) and
|
||||||
|
* distance (adj)
|
||||||
|
*/
|
||||||
|
static double incidenceAngle(double opp, double adj)
|
||||||
|
{
|
||||||
|
return atan2(opp, adj) * 180 / PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Knife edge diffraction:
|
||||||
|
* This is based upon a recognised formula like Huygens, but trades
|
||||||
|
* thoroughness for increased speed which adds a proportional diffraction
|
||||||
|
* effect to obstacles.
|
||||||
|
*/
|
||||||
|
static double ked(double freq, double rxh, double dkm)
|
||||||
|
{
|
||||||
|
double obh, obd, rxobaoi = 0, d;
|
||||||
|
|
||||||
|
obh = 0; // Obstacle height
|
||||||
|
obd = 0; // Obstacle distance
|
||||||
|
|
||||||
|
dkm = dkm * 1000; // KM to metres
|
||||||
|
|
||||||
|
// walk along path
|
||||||
|
for (int n = 2; n < (dkm / elev[1]); n++) {
|
||||||
|
|
||||||
|
d = (n - 2) * elev[1]; // no of points * delta = km
|
||||||
|
|
||||||
|
//Find dip(s)
|
||||||
|
if (elev[n] < obh) {
|
||||||
|
|
||||||
|
// Angle from Rx point to obstacle
|
||||||
|
rxobaoi =
|
||||||
|
incidenceAngle((obh - (elev[n] + rxh)), d - obd);
|
||||||
|
} else {
|
||||||
|
// Line of sight or higher
|
||||||
|
rxobaoi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//note the highest point
|
||||||
|
if (elev[n] > obh) {
|
||||||
|
obh = elev[n];
|
||||||
|
obd = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rxobaoi >= 0) {
|
||||||
|
return (rxobaoi / (300 / freq))+3; // Diffraction angle divided by wavelength (m)
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||||
|
FILE *fd)
|
||||||
|
{
|
||||||
|
/* This function analyzes the path between the source and
|
||||||
|
destination locations. It determines which points along
|
||||||
|
the path have line-of-sight visibility to the source.
|
||||||
|
Points along with path having line-of-sight visibility
|
||||||
|
to the source at an AGL altitude equal to that of the
|
||||||
|
destination location are stored by setting bit 1 in the
|
||||||
|
mask[][] array, which are displayed in green when PPM
|
||||||
|
maps are later generated by ss. */
|
||||||
|
|
||||||
|
char block;
|
||||||
|
int x, y;
|
||||||
|
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||||
|
double distance, rx_alt, tx_alt;
|
||||||
|
|
||||||
|
ReadPath(source, destination);
|
||||||
|
for (y = 0; (y < (path.length - 1) && path.distance[y] <= max_range);
|
||||||
|
y++) {
|
||||||
|
//for (y = 0; y < path.length; y++) {
|
||||||
|
/* Test this point only if it hasn't been already
|
||||||
|
tested and found to be free of obstructions. */
|
||||||
|
|
||||||
|
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0
|
||||||
|
&& can_process(path.lat[y], path.lon[y])) {
|
||||||
|
|
||||||
|
distance = FEET_PER_MILE * path.distance[y];
|
||||||
|
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||||
|
rx_alt =
|
||||||
|
earthradius + destination.alt + path.elevation[y];
|
||||||
|
|
||||||
|
/* Calculate the cosine of the elevation of the
|
||||||
|
transmitter as seen at the temp rx point. */
|
||||||
|
|
||||||
|
cos_xmtr_angle =
|
||||||
|
((rx_alt * rx_alt) + (distance * distance) -
|
||||||
|
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||||
|
|
||||||
|
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||||
|
distance =
|
||||||
|
FEET_PER_MILE * (path.distance[y] -
|
||||||
|
path.distance[x]);
|
||||||
|
test_alt =
|
||||||
|
earthradius + (path.elevation[x] ==
|
||||||
|
0.0 ? path.
|
||||||
|
elevation[x] : path.
|
||||||
|
elevation[x] + clutter);
|
||||||
|
|
||||||
|
cos_test_angle =
|
||||||
|
((rx_alt * rx_alt) + (distance * distance) -
|
||||||
|
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||||
|
distance);
|
||||||
|
|
||||||
|
/* Compare these two angles to determine if
|
||||||
|
an obstruction exists. Since we're comparing
|
||||||
|
the cosines of these angles rather than
|
||||||
|
the angles themselves, the following "if"
|
||||||
|
statement is reversed from what it would
|
||||||
|
be if the actual angles were compared. */
|
||||||
|
|
||||||
|
if (cos_xmtr_angle >= cos_test_angle)
|
||||||
|
block = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block == 0)
|
||||||
|
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotPropPath(struct site source, struct site destination,
|
||||||
|
unsigned char mask_value, FILE * fd, int propmodel,
|
||||||
|
int knifeedge, int pmenv)
|
||||||
|
{
|
||||||
|
|
||||||
|
int x, y, ifs, ofs, errnum;
|
||||||
|
char block = 0, strmode[100];
|
||||||
|
double loss, azimuth, pattern = 0.0,
|
||||||
|
xmtr_alt, dest_alt, xmtr_alt2, dest_alt2,
|
||||||
|
cos_rcvr_angle, cos_test_angle = 0.0, test_alt,
|
||||||
|
elevation = 0.0, distance = 0.0, four_thirds_earth,
|
||||||
|
field_strength = 0.0, rxp, dBm, diffloss;
|
||||||
|
struct site temp;
|
||||||
|
float dkm;
|
||||||
|
|
||||||
|
ReadPath(source, destination);
|
||||||
|
|
||||||
|
four_thirds_earth = FOUR_THIRDS * EARTHRADIUS;
|
||||||
|
|
||||||
|
for (x = 1; x < path.length - 1; x++)
|
||||||
|
elev[x + 2] =
|
||||||
|
(path.elevation[x] ==
|
||||||
|
0.0 ? path.elevation[x] * METERS_PER_FOOT : (clutter +
|
||||||
|
path.
|
||||||
|
elevation[x])
|
||||||
|
* METERS_PER_FOOT);
|
||||||
|
|
||||||
|
|
||||||
|
/* Copy ending points without clutter */
|
||||||
|
|
||||||
|
elev[2] = path.elevation[0] * METERS_PER_FOOT;
|
||||||
|
|
||||||
|
elev[path.length + 1] =
|
||||||
|
path.elevation[path.length - 1] * METERS_PER_FOOT;
|
||||||
|
|
||||||
|
/* Since the only energy the Longley-Rice model considers
|
||||||
|
reaching the destination is based on what is scattered
|
||||||
|
or deflected from the first obstruction along the path,
|
||||||
|
we first need to find the location and elevation angle
|
||||||
|
of that first obstruction (if it exists). This is done
|
||||||
|
using a 4/3rds Earth radius to match the model used by
|
||||||
|
Longley-Rice. This information is required for properly
|
||||||
|
integrating the antenna's elevation pattern into the
|
||||||
|
calculation for overall path loss. */
|
||||||
|
//if(debug)
|
||||||
|
// fprintf(stderr,"four_thirds_earth %.1f source.alt %.1f path.elevation[0] %.1f\n",four_thirds_earth,source.alt,path.elevation[0]);
|
||||||
|
for (y = 2; (y < (path.length - 1) && path.distance[y] <= max_range);
|
||||||
|
y++) {
|
||||||
|
/* Process this point only if it
|
||||||
|
has not already been processed. */
|
||||||
|
|
||||||
|
if ( (GetMask(path.lat[y], path.lon[y]) & 248) !=
|
||||||
|
(mask_value << 3) && can_process(path.lat[y], path.lon[y])) {
|
||||||
|
|
||||||
|
char fd_buffer[64];
|
||||||
|
int buffer_offset = 0;
|
||||||
|
|
||||||
|
distance = FEET_PER_MILE * path.distance[y];
|
||||||
|
xmtr_alt =
|
||||||
|
four_thirds_earth + source.alt + path.elevation[0];
|
||||||
|
dest_alt =
|
||||||
|
four_thirds_earth + destination.alt +
|
||||||
|
path.elevation[y];
|
||||||
|
dest_alt2 = dest_alt * dest_alt;
|
||||||
|
xmtr_alt2 = xmtr_alt * xmtr_alt;
|
||||||
|
|
||||||
|
/* Calculate the cosine of the elevation of
|
||||||
|
the receiver as seen by the transmitter. */
|
||||||
|
|
||||||
|
cos_rcvr_angle =
|
||||||
|
((xmtr_alt2) + (distance * distance) -
|
||||||
|
(dest_alt2)) / (2.0 * xmtr_alt * distance);
|
||||||
|
|
||||||
|
if (cos_rcvr_angle > 1.0)
|
||||||
|
cos_rcvr_angle = 1.0;
|
||||||
|
|
||||||
|
if (cos_rcvr_angle < -1.0)
|
||||||
|
cos_rcvr_angle = -1.0;
|
||||||
|
|
||||||
|
if (got_elevation_pattern || fd != NULL) {
|
||||||
|
/* Determine the elevation angle to the first obstruction
|
||||||
|
along the path IF elevation pattern data is available
|
||||||
|
or an output (.ano) file has been designated. */
|
||||||
|
|
||||||
|
for (x = 2, block = 0; (x < y && block == 0);
|
||||||
|
x++) {
|
||||||
|
distance = FEET_PER_MILE * path.distance[x];
|
||||||
|
|
||||||
|
test_alt =
|
||||||
|
four_thirds_earth +
|
||||||
|
(path.elevation[x] ==
|
||||||
|
0.0 ? path.elevation[x] : path.
|
||||||
|
elevation[x] + clutter);
|
||||||
|
|
||||||
|
/* Calculate the cosine of the elevation
|
||||||
|
angle of the terrain (test point)
|
||||||
|
as seen by the transmitter. */
|
||||||
|
|
||||||
|
cos_test_angle =
|
||||||
|
((xmtr_alt2) +
|
||||||
|
(distance * distance) -
|
||||||
|
(test_alt * test_alt)) / (2.0 *
|
||||||
|
xmtr_alt
|
||||||
|
*
|
||||||
|
distance);
|
||||||
|
|
||||||
|
if (cos_test_angle > 1.0)
|
||||||
|
cos_test_angle = 1.0;
|
||||||
|
|
||||||
|
if (cos_test_angle < -1.0)
|
||||||
|
cos_test_angle = -1.0;
|
||||||
|
|
||||||
|
/* Compare these two angles to determine if
|
||||||
|
an obstruction exists. Since we're comparing
|
||||||
|
the cosines of these angles rather than
|
||||||
|
the angles themselves, the sense of the
|
||||||
|
following "if" statement is reversed from
|
||||||
|
what it would be if the angles themselves
|
||||||
|
were compared. */
|
||||||
|
|
||||||
|
if (cos_rcvr_angle >= cos_test_angle)
|
||||||
|
block = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block)
|
||||||
|
elevation =
|
||||||
|
((acos(cos_test_angle)) / DEG2RAD) -
|
||||||
|
90.0;
|
||||||
|
else
|
||||||
|
elevation =
|
||||||
|
((acos(cos_rcvr_angle)) / DEG2RAD) -
|
||||||
|
90.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine attenuation for each point along the
|
||||||
|
path using a prop model starting at y=2 (number_of_points = 1), the
|
||||||
|
shortest distance terrain can play a role in
|
||||||
|
path loss. */
|
||||||
|
|
||||||
|
elev[0] = y - 1; /* (number of points - 1) */
|
||||||
|
|
||||||
|
/* Distance between elevation samples */
|
||||||
|
|
||||||
|
elev[1] =
|
||||||
|
METERS_PER_MILE * (path.distance[y] -
|
||||||
|
path.distance[y - 1]);
|
||||||
|
|
||||||
|
if (path.elevation[y] < 1) {
|
||||||
|
path.elevation[y] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dkm = (elev[1] * elev[0]) / 1000; // km
|
||||||
|
|
||||||
|
switch (propmodel) {
|
||||||
|
case 1:
|
||||||
|
// Longley Rice ITM
|
||||||
|
point_to_point_ITM(source.alt * METERS_PER_FOOT,
|
||||||
|
destination.alt *
|
||||||
|
METERS_PER_FOOT,
|
||||||
|
LR.eps_dielect,
|
||||||
|
LR.sgm_conductivity,
|
||||||
|
LR.eno_ns_surfref,
|
||||||
|
LR.frq_mhz, LR.radio_climate,
|
||||||
|
LR.pol, LR.conf, LR.rel,
|
||||||
|
loss, strmode, errnum);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//HATA 1, 2 & 3
|
||||||
|
loss =
|
||||||
|
HATApathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||||
|
(path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm, pmenv);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
// ECC33
|
||||||
|
loss =
|
||||||
|
ECC33pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||||
|
(path.elevation[y] *
|
||||||
|
METERS_PER_FOOT) +
|
||||||
|
(destination.alt *
|
||||||
|
METERS_PER_FOOT), dkm,
|
||||||
|
pmenv);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
// SUI
|
||||||
|
loss =
|
||||||
|
SUIpathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||||
|
(path.elevation[y] *
|
||||||
|
METERS_PER_FOOT) +
|
||||||
|
(destination.alt *
|
||||||
|
METERS_PER_FOOT), dkm, pmenv);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
// COST231-Hata
|
||||||
|
loss =
|
||||||
|
COST231pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||||
|
(path.elevation[y] *
|
||||||
|
METERS_PER_FOOT) +
|
||||||
|
(destination.alt *
|
||||||
|
METERS_PER_FOOT), dkm,
|
||||||
|
pmenv);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
// ITU-R P.525 Free space path loss
|
||||||
|
loss = FSPLpathLoss(LR.frq_mhz, dkm);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
// ITWOM 3.0
|
||||||
|
point_to_point(source.alt * METERS_PER_FOOT,
|
||||||
|
destination.alt *
|
||||||
|
METERS_PER_FOOT, LR.eps_dielect,
|
||||||
|
LR.sgm_conductivity,
|
||||||
|
|
||||||
|
LR.eno_ns_surfref, LR.frq_mhz,
|
||||||
|
LR.radio_climate, LR.pol,
|
||||||
|
LR.conf, LR.rel, loss, strmode,
|
||||||
|
errnum);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
// Ericsson
|
||||||
|
loss =
|
||||||
|
EricssonpathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT,
|
||||||
|
(path.elevation[y] *
|
||||||
|
METERS_PER_FOOT) +
|
||||||
|
(destination.alt *
|
||||||
|
METERS_PER_FOOT), dkm,
|
||||||
|
pmenv);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
// Plane earth
|
||||||
|
loss = PlaneEarthLoss(dkm, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT));
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
// Egli VHF/UHF
|
||||||
|
loss = EgliPathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT),dkm);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
// Soil
|
||||||
|
loss = SoilPathLoss(LR.frq_mhz, dkm, LR.eps_dielect);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
point_to_point_ITM(source.alt * METERS_PER_FOOT,
|
||||||
|
destination.alt *
|
||||||
|
METERS_PER_FOOT,
|
||||||
|
LR.eps_dielect,
|
||||||
|
LR.sgm_conductivity,
|
||||||
|
LR.eno_ns_surfref,
|
||||||
|
LR.frq_mhz, LR.radio_climate,
|
||||||
|
LR.pol, LR.conf, LR.rel,
|
||||||
|
loss, strmode, errnum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (knifeedge == 1 && propmodel > 1) {
|
||||||
|
diffloss =
|
||||||
|
ked(LR.frq_mhz,
|
||||||
|
destination.alt * METERS_PER_FOOT, dkm);
|
||||||
|
loss += (diffloss); // ;)
|
||||||
|
}
|
||||||
|
//Key stage. Link dB for p2p is returned as 'loss'.
|
||||||
|
|
||||||
|
temp.lat = path.lat[y];
|
||||||
|
temp.lon = path.lon[y];
|
||||||
|
|
||||||
|
azimuth = (Azimuth(source, temp));
|
||||||
|
|
||||||
|
if (fd != NULL)
|
||||||
|
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||||
|
"%.7f, %.7f, %.3f, %.3f, ",
|
||||||
|
path.lat[y], path.lon[y], azimuth,
|
||||||
|
elevation);
|
||||||
|
|
||||||
|
/* If ERP==0, write path loss to alphanumeric
|
||||||
|
output file. Otherwise, write field strength
|
||||||
|
or received power level (below), as appropriate. */
|
||||||
|
|
||||||
|
if (fd != NULL && LR.erp == 0.0)
|
||||||
|
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||||
|
"%.2f", loss);
|
||||||
|
|
||||||
|
/* Integrate the antenna's radiation
|
||||||
|
pattern into the overall path loss. */
|
||||||
|
|
||||||
|
x = (int)rint(10.0 * (10.0 - elevation));
|
||||||
|
|
||||||
|
if (x >= 0 && x <= 1000) {
|
||||||
|
azimuth = rint(azimuth);
|
||||||
|
|
||||||
|
pattern =
|
||||||
|
(double)LR.antenna_pattern[(int)azimuth][x];
|
||||||
|
|
||||||
|
if (pattern != 0.0) {
|
||||||
|
pattern = 20.0 * log10(pattern);
|
||||||
|
loss -= pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LR.erp != 0.0) {
|
||||||
|
if (dbm) {
|
||||||
|
/* dBm is based on EIRP (ERP + 2.14) */
|
||||||
|
|
||||||
|
rxp =
|
||||||
|
LR.erp /
|
||||||
|
(pow(10.0, (loss - 2.14) / 10.0));
|
||||||
|
|
||||||
|
dBm = 10.0 * (log10(rxp * 1000.0));
|
||||||
|
|
||||||
|
if (fd != NULL)
|
||||||
|
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||||
|
"%.3f", dBm);
|
||||||
|
|
||||||
|
/* Scale roughly between 0 and 255 */
|
||||||
|
|
||||||
|
ifs = 200 + (int)rint(dBm);
|
||||||
|
|
||||||
|
if (ifs < 0)
|
||||||
|
ifs = 0;
|
||||||
|
|
||||||
|
if (ifs > 255)
|
||||||
|
ifs = 255;
|
||||||
|
|
||||||
|
ofs =
|
||||||
|
GetSignal(path.lat[y], path.lon[y]);
|
||||||
|
|
||||||
|
if (ofs > ifs)
|
||||||
|
ifs = ofs;
|
||||||
|
|
||||||
|
PutSignal(path.lat[y], path.lon[y],
|
||||||
|
(unsigned char)ifs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
field_strength =
|
||||||
|
(139.4 +
|
||||||
|
(20.0 * log10(LR.frq_mhz)) -
|
||||||
|
loss) +
|
||||||
|
(10.0 * log10(LR.erp / 1000.0));
|
||||||
|
|
||||||
|
ifs = 100 + (int)rint(field_strength);
|
||||||
|
|
||||||
|
if (ifs < 0)
|
||||||
|
ifs = 0;
|
||||||
|
|
||||||
|
if (ifs > 255)
|
||||||
|
ifs = 255;
|
||||||
|
|
||||||
|
ofs =
|
||||||
|
GetSignal(path.lat[y], path.lon[y]);
|
||||||
|
|
||||||
|
if (ofs > ifs)
|
||||||
|
ifs = ofs;
|
||||||
|
|
||||||
|
PutSignal(path.lat[y], path.lon[y],
|
||||||
|
(unsigned char)ifs);
|
||||||
|
|
||||||
|
if (fd != NULL)
|
||||||
|
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||||
|
"%.3f",
|
||||||
|
field_strength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (loss > 255)
|
||||||
|
ifs = 255;
|
||||||
|
else
|
||||||
|
ifs = (int)rint(loss);
|
||||||
|
|
||||||
|
ofs = GetSignal(path.lat[y], path.lon[y]);
|
||||||
|
|
||||||
|
if (ofs < ifs && ofs != 0)
|
||||||
|
ifs = ofs;
|
||||||
|
|
||||||
|
PutSignal(path.lat[y], path.lon[y],
|
||||||
|
(unsigned char)ifs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd != NULL) {
|
||||||
|
if (block)
|
||||||
|
buffer_offset += sprintf(fd_buffer+buffer_offset,
|
||||||
|
" *");
|
||||||
|
fprintf(fd, "%s\n", fd_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark this point as having been analyzed */
|
||||||
|
|
||||||
|
PutMask(path.lat[y], path.lon[y],
|
||||||
|
(GetMask(path.lat[y], path.lon[y]) & 7) +
|
||||||
|
(mask_value << 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(path.lat[y]>cropLat)
|
||||||
|
cropLat=path.lat[y];
|
||||||
|
|
||||||
|
|
||||||
|
if(y>cropLon)
|
||||||
|
cropLon=y;
|
||||||
|
|
||||||
|
//if(cropLon>180)
|
||||||
|
// cropLon-=360;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotLOSMap(struct site source, double altitude, char *plo_filename,
|
||||||
|
bool use_threads)
|
||||||
|
{
|
||||||
|
/* This function performs a 360 degree sweep around the
|
||||||
|
transmitter site (source location), and plots the
|
||||||
|
line-of-sight coverage of the transmitter on the ss
|
||||||
|
generated topographic map based on a receiver located
|
||||||
|
at the specified altitude (in feet AGL). Results
|
||||||
|
are stored in memory, and written out in the form
|
||||||
|
of a topographic map when the WritePPM() function
|
||||||
|
is later invoked. */
|
||||||
|
|
||||||
|
static __thread unsigned char mask_value = 1;
|
||||||
|
FILE *fd = NULL;
|
||||||
|
|
||||||
|
if (plo_filename[0] != 0)
|
||||||
|
fd = fopen(plo_filename, "wb");
|
||||||
|
|
||||||
|
if (fd != NULL) {
|
||||||
|
fprintf(fd,
|
||||||
|
"%.3f, %.3f\t; max_west, min_west\n%.3f, %.3f\t; max_north, min_north\n",
|
||||||
|
max_west, min_west, max_north, min_north);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Four sections start here
|
||||||
|
// Process north edge east/west, east edge north/south,
|
||||||
|
// south edge east/west, west edge north/south
|
||||||
|
double range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||||
|
double range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||||
|
double range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||||
|
double range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||||
|
propagationRange* r[NUM_SECTIONS];
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||||
|
propagationRange *range = new propagationRange;
|
||||||
|
r[i] = range;
|
||||||
|
range->los = true;
|
||||||
|
|
||||||
|
range->eastwest = (range_min_west[i] == range_max_west[i] ? false : true);
|
||||||
|
range->min_west = range_min_west[i];
|
||||||
|
range->max_west = range_max_west[i];
|
||||||
|
range->min_north = range_min_north[i];
|
||||||
|
range->max_north = range_max_north[i];
|
||||||
|
|
||||||
|
range->use_threads = use_threads;
|
||||||
|
range->altitude = altitude;
|
||||||
|
range->source = source;
|
||||||
|
range->mask_value = mask_value;
|
||||||
|
range->fd = fd;
|
||||||
|
|
||||||
|
if(use_threads)
|
||||||
|
beginThread(range);
|
||||||
|
else
|
||||||
|
rangePropagation(range);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(use_threads)
|
||||||
|
finishThreads();
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||||
|
delete r[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mask_value) {
|
||||||
|
case 1:
|
||||||
|
mask_value = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
mask_value = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
mask_value = 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||||
|
int propmodel, int knifeedge, int haf, int pmenv, bool
|
||||||
|
use_threads)
|
||||||
|
{
|
||||||
|
static __thread unsigned char mask_value = 1;
|
||||||
|
FILE *fd = NULL;
|
||||||
|
|
||||||
|
if (LR.erp == 0.0 && debug)
|
||||||
|
fprintf(stderr, "path loss");
|
||||||
|
else {
|
||||||
|
if (debug) {
|
||||||
|
if (dbm)
|
||||||
|
fprintf(stderr, "signal power level");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "field strength");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debug) {
|
||||||
|
fprintf(stderr,
|
||||||
|
" contours of \"%s\" out to a radius of %.2f %s with Rx antenna(s) at %.2f %s AGL\n",
|
||||||
|
source.name,
|
||||||
|
metric ? max_range * KM_PER_MILE : max_range,
|
||||||
|
metric ? "kilometers" : "miles",
|
||||||
|
metric ? altitude * METERS_PER_FOOT : altitude,
|
||||||
|
metric ? "meters" : "feet");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clutter > 0.0 && debug)
|
||||||
|
fprintf(stderr, "\nand %.2f %s of ground clutter",
|
||||||
|
metric ? clutter * METERS_PER_FOOT : clutter,
|
||||||
|
metric ? "meters" : "feet");
|
||||||
|
|
||||||
|
if (plo_filename[0] != 0)
|
||||||
|
fd = fopen(plo_filename, "wb");
|
||||||
|
|
||||||
|
if (fd != NULL) {
|
||||||
|
fprintf(fd,
|
||||||
|
"%.3f, %.3f\t; max_west, min_west\n%.3f, %.3f\t; max_north, min_north\n",
|
||||||
|
max_west, min_west, max_north, min_north);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Four sections start here
|
||||||
|
// Process north edge east/west, east edge north/south,
|
||||||
|
// south edge east/west, west edge north/south
|
||||||
|
double range_min_west[] = {min_west, min_west, min_west, max_west};
|
||||||
|
double range_min_north[] = {max_north, min_north, min_north, min_north};
|
||||||
|
double range_max_west[] = {max_west, min_west, max_west, max_west};
|
||||||
|
double range_max_north[] = {max_north, max_north, min_north, max_north};
|
||||||
|
propagationRange* r[NUM_SECTIONS];
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_SECTIONS; ++i) {
|
||||||
|
propagationRange *range = new propagationRange;
|
||||||
|
r[i] = range;
|
||||||
|
range->los = false;
|
||||||
|
|
||||||
|
// Only process correct half
|
||||||
|
if((NUM_SECTIONS - i) <= (NUM_SECTIONS / 2) && haf == 1)
|
||||||
|
continue;
|
||||||
|
if((NUM_SECTIONS - i) > (NUM_SECTIONS / 2) && haf == 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
range->eastwest = (range_min_west[i] == range_max_west[i] ? false : true);
|
||||||
|
range->min_west = range_min_west[i];
|
||||||
|
range->max_west = range_max_west[i];
|
||||||
|
range->min_north = range_min_north[i];
|
||||||
|
range->max_north = range_max_north[i];
|
||||||
|
|
||||||
|
range->use_threads = use_threads;
|
||||||
|
range->altitude = altitude;
|
||||||
|
range->source = source;
|
||||||
|
range->mask_value = mask_value;
|
||||||
|
range->fd = fd;
|
||||||
|
range->propmodel = propmodel;
|
||||||
|
range->knifeedge = knifeedge;
|
||||||
|
range->pmenv = pmenv;
|
||||||
|
|
||||||
|
if(use_threads)
|
||||||
|
beginThread(range);
|
||||||
|
else
|
||||||
|
rangePropagation(range);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(use_threads)
|
||||||
|
finishThreads();
|
||||||
|
|
||||||
|
for(int i = 0; i < NUM_SECTIONS; ++i){
|
||||||
|
delete r[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd != NULL)
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if (mask_value < 30)
|
||||||
|
mask_value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotPath(struct site source, struct site destination, char mask_value)
|
||||||
|
{
|
||||||
|
/* This function analyzes the path between the source and
|
||||||
|
destination locations. It determines which points along
|
||||||
|
the path have line-of-sight visibility to the source.
|
||||||
|
Points along with path having line-of-sight visibility
|
||||||
|
to the source at an AGL altitude equal to that of the
|
||||||
|
destination location are stored by setting bit 1 in the
|
||||||
|
mask[][] array, which are displayed in green when PPM
|
||||||
|
maps are later generated by SPLAT!. */
|
||||||
|
|
||||||
|
char block;
|
||||||
|
int x, y;
|
||||||
|
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||||
|
double distance, rx_alt, tx_alt;
|
||||||
|
|
||||||
|
ReadPath(source, destination);
|
||||||
|
|
||||||
|
for (y = 0; y < path.length; y++) {
|
||||||
|
/* Test this point only if it hasn't been already
|
||||||
|
tested and found to be free of obstructions. */
|
||||||
|
|
||||||
|
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0) {
|
||||||
|
distance = FEET_PER_MILE * path.distance[y];
|
||||||
|
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||||
|
rx_alt =
|
||||||
|
earthradius + destination.alt + path.elevation[y];
|
||||||
|
|
||||||
|
/* Calculate the cosine of the elevation of the
|
||||||
|
transmitter as seen at the temp rx point. */
|
||||||
|
|
||||||
|
cos_xmtr_angle =
|
||||||
|
((rx_alt * rx_alt) + (distance * distance) -
|
||||||
|
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||||
|
|
||||||
|
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||||
|
distance =
|
||||||
|
FEET_PER_MILE * (path.distance[y] -
|
||||||
|
path.distance[x]);
|
||||||
|
test_alt =
|
||||||
|
earthradius + (path.elevation[x] ==
|
||||||
|
0.0 ? path.
|
||||||
|
elevation[x] : path.
|
||||||
|
elevation[x] + clutter);
|
||||||
|
|
||||||
|
cos_test_angle =
|
||||||
|
((rx_alt * rx_alt) + (distance * distance) -
|
||||||
|
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||||
|
distance);
|
||||||
|
|
||||||
|
/* Compare these two angles to determine if
|
||||||
|
an obstruction exists. Since we're comparing
|
||||||
|
the cosines of these angles rather than
|
||||||
|
the angles themselves, the following "if"
|
||||||
|
statement is reversed from what it would
|
||||||
|
be if the actual angles were compared. */
|
||||||
|
|
||||||
|
if (cos_xmtr_angle >= cos_test_angle)
|
||||||
|
block = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block == 0)
|
||||||
|
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/models/los.hh
Normal file
18
src/models/los.hh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _LOS_HH_
|
||||||
|
#define _LOS_HH_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||||
|
FILE *fd);
|
||||||
|
void PlotPropPath(struct site source, struct site destination,
|
||||||
|
unsigned char mask_value, FILE * fd, int propmodel,
|
||||||
|
int knifeedge, int pmenv);
|
||||||
|
void PlotLOSMap(struct site source, double altitude, char *plo_filename, bool use_threads);
|
||||||
|
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||||
|
int propmodel, int knifeedge, int haf, int pmenv, bool use_threads);
|
||||||
|
void PlotPath(struct site source, struct site destination, char mask_value);
|
||||||
|
|
||||||
|
#endif /* _LOS_HH_ */
|
29
src/models/pel.cc
Normal file
29
src/models/pel.cc
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Plane Earth Path Loss model for Signal Server by Alex Farrant *
|
||||||
|
* Taken from "Antennas and Propagation for wireless communication systems" *
|
||||||
|
* ISBN 978-0-470-84879-1 *
|
||||||
|
* 10 August 2016 *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double PlaneEarthLoss(float d, float TxH, float RxH)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Plane Earth Loss model
|
||||||
|
Frequency: N/A
|
||||||
|
Distance (km): Any
|
||||||
|
*/
|
||||||
|
// Plane earth loss is independent of frequency.
|
||||||
|
double dbloss = 40*log10(d) + 20*log10(TxH) + 20*log10(RxH);
|
||||||
|
return dbloss;
|
||||||
|
}
|
6
src/models/pel.hh
Normal file
6
src/models/pel.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _PEL_HH_
|
||||||
|
#define _PEL_HH_
|
||||||
|
|
||||||
|
double PlaneEarthLoss(float d, float TxH, float RxH);
|
||||||
|
|
||||||
|
#endif /* _PEL_HH_ */
|
33
src/models/soil.cc
Normal file
33
src/models/soil.cc
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Soil Path Loss model for Signal Server by Alex Farrant *
|
||||||
|
* 21 February 2018 *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
*
|
||||||
|
* Frequency: Any MHz
|
||||||
|
* Distance: Any Km
|
||||||
|
* Terrain permittivity: 1 - 15 (Bad to Good)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// use call with log/ln as this may be faster
|
||||||
|
// use constant of value 20.0/log(10.0)
|
||||||
|
static __inline float _20log10f(float x)
|
||||||
|
{
|
||||||
|
return(8.685889f*logf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
double SoilPathLoss(float f, float d, float terdic)
|
||||||
|
{
|
||||||
|
float soil = (120/terdic);
|
||||||
|
return(6.4 + _20log10f(d) + _20log10f(f)+(8.69*soil));
|
||||||
|
}
|
6
src/models/soil.hh
Normal file
6
src/models/soil.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _SOIL_HH_
|
||||||
|
#define _SOIL_HH_
|
||||||
|
|
||||||
|
double SoilPathLoss(float f, float d, float t);
|
||||||
|
|
||||||
|
#endif /* _SOIL_HH_ */
|
65
src/models/sui.cc
Normal file
65
src/models/sui.cc
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
// use call with log/ln as this may be faster
|
||||||
|
// use constant of value 20.0/log(10.0)
|
||||||
|
static __inline float _20log10f(float x)
|
||||||
|
{
|
||||||
|
return(8.685889f*logf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
f = Frequency (MHz) 1900 to 11000
|
||||||
|
TxH = Transmitter height (m)
|
||||||
|
RxH = Receiver height (m)
|
||||||
|
d = distance (km)
|
||||||
|
mode A1 = URBAN / OBSTRUCTED
|
||||||
|
mode B2 = SUBURBAN / PARTIALLY OBSTRUCTED
|
||||||
|
mode C3 = RURAL / OPEN
|
||||||
|
Paper 1 has a Rx height correction of / 2000
|
||||||
|
Paper 2 has the same correction as / 2 and gives better results
|
||||||
|
"Ranked number 2 University in the wurld"
|
||||||
|
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||||
|
https://mentor.ieee.org/802.19/file/08/19-08-0010-00-0000-sui-path-loss-model.doc
|
||||||
|
*/
|
||||||
|
d *= 1e3; // km to m
|
||||||
|
|
||||||
|
// Urban (A1) is default
|
||||||
|
float a = 4.6;
|
||||||
|
float b = 0.0075;
|
||||||
|
float c = 12.6;
|
||||||
|
float s = 8.2; // Optional fading value. 8.2 to 10.6dB
|
||||||
|
float XhCF = -10.8;
|
||||||
|
|
||||||
|
if (mode == 2) { // Suburban
|
||||||
|
a = 4.0;
|
||||||
|
b = 0.0065;
|
||||||
|
c = 17.1;
|
||||||
|
XhCF = -10.8;
|
||||||
|
}
|
||||||
|
if (mode == 3) { // Rural
|
||||||
|
a = 3.6;
|
||||||
|
b = 0.005;
|
||||||
|
c = 20;
|
||||||
|
XhCF = -20;
|
||||||
|
}
|
||||||
|
float d0 = 100.0;
|
||||||
|
float A = _20log10f((4 * M_PI * d0) / (300.0 / f));
|
||||||
|
float y = a - (b * TxH) + (c / TxH);
|
||||||
|
|
||||||
|
// Assume 2.4GHz
|
||||||
|
float Xf = 0;
|
||||||
|
float Xh = 0;
|
||||||
|
|
||||||
|
//Correction factors for > 2GHz
|
||||||
|
if(f>2000){
|
||||||
|
Xf=6.0 * log10(f / 2.0);
|
||||||
|
Xh=XhCF * log10(RxH / 2.0);
|
||||||
|
}
|
||||||
|
return A + (10 * y) * (log10(d / d0)) + Xf + Xh + s;
|
||||||
|
}
|
6
src/models/sui.hh
Normal file
6
src/models/sui.hh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _SUI_HH_
|
||||||
|
#define _SUI_HH_
|
||||||
|
|
||||||
|
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
|
||||||
|
|
||||||
|
#endif /* _SUI_HH_ */
|
118
src/models/testmodels.cc
Normal file
118
src/models/testmodels.cc
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
/*
|
||||||
|
* Propagation model test script for signal server
|
||||||
|
* Requires gnuplot
|
||||||
|
* Compile: gcc -Wall -o test test.cc sui.cc cost.cc ecc33.cc ericsson.cc fspl.cc egli.cc hata.cc -lm
|
||||||
|
* Test 850Mhz: ./test 850
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU General Public License as published by the *
|
||||||
|
* Free Software Foundation; either version 2 of the License or any later *
|
||||||
|
* version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will useful, but WITHOUT *
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
|
||||||
|
* for more details. *
|
||||||
|
* *
|
||||||
|
\****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
extern double EgliPathLoss(float f, float TxH, float RxH, float d);
|
||||||
|
extern double SUIpathLoss(double f, double TxH, double RxH, double d, int mode);
|
||||||
|
extern double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
extern double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
extern double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
extern double FSPLpathLoss(float f, float d);
|
||||||
|
extern double HATApathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||||
|
extern void point_to_point_ITM(double tht_m, double rht_m, double eps_dielect,
|
||||||
|
double sgm_conductivity, double eno_ns_surfref,
|
||||||
|
double frq_mhz, int radio_climate, int pol,
|
||||||
|
double conf, double rel, double &dbloss, char *strmode,
|
||||||
|
int &errnum);
|
||||||
|
__thread double *elev;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
double a = 0;
|
||||||
|
double f = atof(argv[1]);
|
||||||
|
double r = 5.0;
|
||||||
|
float TxH = 30.0;
|
||||||
|
float RxH = 2.0;
|
||||||
|
|
||||||
|
mkdir("tests", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||||
|
|
||||||
|
FILE * fh;
|
||||||
|
|
||||||
|
/*fh = fopen("tests/ITM","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.2){
|
||||||
|
point_to_point_ITM(TxH,RxH,15.0,0.005,301.0,f,5,1,0.5,0.5,a,"",errno);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
*/
|
||||||
|
fh = fopen("tests/SUI.1","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = SUIpathLoss(f, TxH, RxH, d,1);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
fh = fopen("tests/COST231.1","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = COST231pathLoss(f, TxH, RxH, d,1);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
|
||||||
|
fh = fopen("tests/ECC33.1","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = ECC33pathLoss(f, TxH, RxH, d,1);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
fh = fopen("tests/Ericsson9999.1","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = EricssonpathLoss(f, TxH, RxH, d,1);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
fh = fopen("tests/FSPL","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = FSPLpathLoss(f, d);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
fh = fopen("tests/Hata.1","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = HATApathLoss(f, TxH, RxH, d, 1);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
fh = fopen("tests/Egli.VHF-UHF","w");
|
||||||
|
for(float d = 0.1; d <= r; d=d+0.1){
|
||||||
|
a = EgliPathLoss(f, TxH, RxH, d);
|
||||||
|
fprintf(fh,"%.1f\t%.1f\n",d,a);
|
||||||
|
}
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
|
||||||
|
fh = fopen("tests/gnuplot.plt","w");
|
||||||
|
fprintf(fh,"set terminal jpeg size 800,600\nset output '%.0fMHz_propagation_models.jpg'\nset title '%.0fMHz path loss by propagation model - CloudRF.com'\n",f,f);
|
||||||
|
fprintf(fh,"set key right bottom box\nset style line 1\nset grid\nset xlabel 'Distance KM'\nset ylabel 'Path Loss dB'\n");
|
||||||
|
fprintf(fh,"plot 'FSPL' with lines, 'Hata.1' with lines, 'COST231.1' with lines,'ECC33.1' with lines,'Ericsson9999.1' with lines,'SUI.1' with lines,'Egli.VHF-UHF' with lines");
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
system("cd tests && gnuplot gnuplot.plt");
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
2024
src/outputs.cc
Normal file
2024
src/outputs.cc
Normal file
File diff suppressed because it is too large
Load Diff
17
src/outputs.hh
Normal file
17
src/outputs.hh
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _OUTPUT_HH_
|
||||||
|
#define _OUTPUT_HH_
|
||||||
|
|
||||||
|
void DoPathLoss(char *filename, unsigned char geo, unsigned char kml,
|
||||||
|
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||||
|
int DoSigStr(char *filename, unsigned char geo, unsigned char kml,
|
||||||
|
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||||
|
void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml,
|
||||||
|
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||||
|
void DoLOS(char *filename, unsigned char geo, unsigned char kml,
|
||||||
|
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||||
|
void PathReport(struct site source, struct site destination, char *name,
|
||||||
|
char graph_it, int propmodel, int pmenv, double rxGain);
|
||||||
|
void SeriesData(struct site source, struct site destination, char *name,
|
||||||
|
unsigned char fresnel_plot, unsigned char normalised);
|
||||||
|
|
||||||
|
#endif /* _OUTPUT_HH_ */
|
64
src/suitest.cc
Normal file
64
src/suitest.cc
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
// use call with log/ln as this may be faster
|
||||||
|
// use constant of value 20.0/log(10.0)
|
||||||
|
static __inline float _20log10f(float x)
|
||||||
|
{
|
||||||
|
return(8.685889f*logf(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
double SUIpathLoss(double f, double TxH, double RxH, double d, int mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
f = Frequency (MHz) 1900 to 11000
|
||||||
|
TxH = Transmitter height (m)
|
||||||
|
RxH = Receiver height (m)
|
||||||
|
d = distance (km)
|
||||||
|
mode A1 = URBAN / OBSTRUCTED
|
||||||
|
mode B2 = SUBURBAN / PARTIALLY OBSTRUCTED
|
||||||
|
mode C3 = RURAL / OPEN
|
||||||
|
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||||
|
*/
|
||||||
|
//f /=1e3;
|
||||||
|
d *= 1e3; // km to m
|
||||||
|
|
||||||
|
// Urban (A1) is default
|
||||||
|
float a = 4.6;
|
||||||
|
float b = 0.0075;
|
||||||
|
float c = 12.6;
|
||||||
|
float s = 10.6; // Optional fading value. Max 10.6dB
|
||||||
|
float XhCF = -10.8;
|
||||||
|
|
||||||
|
if (mode == 2) { // Suburban
|
||||||
|
a = 4.0;
|
||||||
|
b = 0.0065;
|
||||||
|
c = 17.1;
|
||||||
|
}
|
||||||
|
if (mode == 3) { // Rural
|
||||||
|
a = 3.6;
|
||||||
|
b = 0.005;
|
||||||
|
c = 20;
|
||||||
|
XhCF = -20;
|
||||||
|
}
|
||||||
|
float d0 = 100;
|
||||||
|
float A = _20log10f((4 * M_PI * d0) / (300.0 / f));
|
||||||
|
float y = a - (b * TxH) + (c / TxH);
|
||||||
|
//Correction factors
|
||||||
|
float Xf = 6.0 * log10(f / 2000.0);
|
||||||
|
float Xh = XhCF * log10(RxH / 2000.0);
|
||||||
|
Xh *=-1;
|
||||||
|
fprintf(stdout,"A %lf y %lf Xf %lf Xh %lf\n",A,y,Xf,Xh);
|
||||||
|
return A + (10 * y * log10(d / d0)) + Xf + Xh + s;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
|
||||||
|
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,1));
|
||||||
|
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,2));
|
||||||
|
fprintf(stdout,"%lf\n",SUIpathLoss(3500.0,15.0,10.0,1,3));
|
||||||
|
}
|
BIN
src/testmodels.o
Normal file
BIN
src/testmodels.o
Normal file
Binary file not shown.
246
src/tiles.cc
Normal file
246
src/tiles.cc
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "tiles.hh"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define MAX_LINE 50000
|
||||||
|
|
||||||
|
/* Computes the distance between two long/lat points */
|
||||||
|
double haversine_formula(double th1, double ph1, double th2, double ph2)
|
||||||
|
{
|
||||||
|
#define TO_RAD (3.1415926536 / 180)
|
||||||
|
int R = 6371;
|
||||||
|
double dx, dy, dz;
|
||||||
|
ph1 -= ph2;
|
||||||
|
ph1 *= TO_RAD, th1 *= TO_RAD, th2 *= TO_RAD;
|
||||||
|
dz = sin(th1) - sin(th2);
|
||||||
|
dx = cos(ph1) * cos(th1) - cos(th2);
|
||||||
|
dy = sin(ph1) * cos(th1);
|
||||||
|
return asin(sqrt(dx * dx + dy * dy + dz * dz) / 2) * 2 * R;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tile_load_lidar(tile_t *tile, char *filename){
|
||||||
|
FILE *fd;
|
||||||
|
char line[MAX_LINE];
|
||||||
|
short nextval;
|
||||||
|
char *pch;
|
||||||
|
|
||||||
|
/* Clear the tile data */
|
||||||
|
memset(tile, 0x00, sizeof(tile_t));
|
||||||
|
|
||||||
|
/* Open the file handle and return on error */
|
||||||
|
if ( (fd = fopen(filename,"r")) == NULL )
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
/* This is where we read the header data */
|
||||||
|
/* The string is split for readability but is parsed as a block */
|
||||||
|
if( fscanf(fd,"%*s %d\n" "%*s %d\n" "%*s %lf\n" "%*s %lf\n" "%*s %lf\n" "%*s %d\n",&tile->width,&tile->height,&tile->xll,&tile->yll,&tile->cellsize,(int *)&tile->nodata) != 6 ){
|
||||||
|
fclose(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile->datastart = ftell(fd);
|
||||||
|
|
||||||
|
if(debug){
|
||||||
|
fprintf(stderr,"w:%d h:%d s:%lf\n", tile->width, tile->height, tile->cellsize);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the filename */
|
||||||
|
tile->filename = strdup(filename);
|
||||||
|
|
||||||
|
/* Perform xur calcs */
|
||||||
|
tile->xur = tile->xll+(tile->cellsize*tile->width);
|
||||||
|
tile->yur = tile->yll+(tile->cellsize*tile->height);
|
||||||
|
|
||||||
|
if (tile->xur > eastoffset)
|
||||||
|
eastoffset = tile->xur;
|
||||||
|
if (tile->xll < westoffset)
|
||||||
|
westoffset = tile->xll;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr,"%d, %d, %.7f, %.7f, %.7f, %.7f, %.7f\n",tile->width,tile->height,tile->xll,tile->yll,tile->cellsize,tile->yur,tile->xur);
|
||||||
|
|
||||||
|
// Greenwich straddling hack
|
||||||
|
/* if (tile->xll <= 0 && tile->xur > 0) {
|
||||||
|
tile->xll = (tile->xur - tile->xll); // full width
|
||||||
|
tile->xur = 0.0; // budge it along so it's west of greenwich
|
||||||
|
delta = eastoffset; // add to Tx longitude later
|
||||||
|
} else {*/
|
||||||
|
// Transform WGS84 longitudes into 'west' values as society finishes east of Greenwich ;)
|
||||||
|
if (tile->xll >= 0)
|
||||||
|
tile->xll = 360-tile->xll;
|
||||||
|
if(tile->xur >= 0)
|
||||||
|
tile->xur = 360-tile->xur;
|
||||||
|
if(tile->xll < 0)
|
||||||
|
tile->xll = tile->xll * -1;
|
||||||
|
if(tile->xur < 0)
|
||||||
|
tile->xur = tile->xur * -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "POST yll %.7f yur %.7f xur %.7f xll %.7f delta %.6f\n", tile->yll, tile->yur, tile->xur, tile->xll, delta);
|
||||||
|
|
||||||
|
/* Read the actual tile data */
|
||||||
|
/* Allocate the array for the lidar data */
|
||||||
|
if ( (tile->data = (short*) calloc(tile->width * tile->height, sizeof(short))) == NULL ) {
|
||||||
|
fclose(fd);
|
||||||
|
free(tile->filename);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t loaded = 0;
|
||||||
|
for (size_t h = 0; h < (unsigned)tile->height; h++) {
|
||||||
|
if (fgets(line, MAX_LINE, fd) != NULL) {
|
||||||
|
pch = strtok(line, " "); // split line into values
|
||||||
|
for (size_t w = 0; w < (unsigned)tile->width && pch != NULL; w++) {
|
||||||
|
/* If the data is less than a *magic* minimum, normalize it to zero */
|
||||||
|
nextval = atoi(pch);
|
||||||
|
if (nextval <= 0)
|
||||||
|
nextval = 0;
|
||||||
|
tile->data[h*tile->width + w] = nextval;
|
||||||
|
loaded++;
|
||||||
|
if ( nextval > tile->max_el )
|
||||||
|
tile->max_el = nextval;
|
||||||
|
if ( nextval < tile->min_el )
|
||||||
|
tile->min_el = nextval;
|
||||||
|
pch = strtok(NULL, " ");
|
||||||
|
}//while
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "LIDAR error @ h %zu file %s\n", h, filename);
|
||||||
|
}//if
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_res_km = haversine_formula(tile->max_north, tile->max_west, tile->max_north, tile->min_west);
|
||||||
|
tile->precise_resolution = (current_res_km/MAX(tile->width,tile->height)*1000);
|
||||||
|
|
||||||
|
// Round to nearest 0.5
|
||||||
|
tile->resolution = tile->precise_resolution < 0.5f ? 0.5f : ceil((tile->precise_resolution * 2)+0.5) / 2;
|
||||||
|
|
||||||
|
// Positive westing
|
||||||
|
tile->width_deg = tile->max_west - tile->min_west >= 0 ? tile->max_west - tile->min_west : tile->max_west + (360 - tile->min_west);
|
||||||
|
tile->height_deg = tile->max_north - tile->min_north;
|
||||||
|
|
||||||
|
tile->ppdx = tile->width / tile->width_deg;
|
||||||
|
tile->ppdy = tile->height / tile->height_deg;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr,"Pixels loaded: %zu/%d (PPD %dx%d, Res %f (%.2f))\n", loaded, tile->width*tile->height, tile->ppdx, tile->ppdy, tile->precise_resolution, tile->resolution);
|
||||||
|
|
||||||
|
/* All done, close the LIDAR file */
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tile_rescale
|
||||||
|
* This is used to resample tile data. It is particularly designed for
|
||||||
|
* use with LIDAR tiles where the resolution can be anything up to 2m.
|
||||||
|
* This function is capable of merging neighbouring pixel values
|
||||||
|
* The scaling factor is the distance to merge pixels.
|
||||||
|
* NOTE: This means that new resolutions can only increment in multiples of the original
|
||||||
|
* (ie 2m LIDAR can be 4/6/8/... and 20m can be 40/60)
|
||||||
|
*/
|
||||||
|
int tile_rescale(tile_t *tile, float scale){
|
||||||
|
short *new_data;
|
||||||
|
size_t skip_count = 1;
|
||||||
|
size_t copy_count = 1;
|
||||||
|
|
||||||
|
if (scale == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t new_height = tile->height * scale;
|
||||||
|
size_t new_width = tile->width * scale;
|
||||||
|
|
||||||
|
/* Allocate the array for the lidar data */
|
||||||
|
if ( (new_data = (short*) calloc(new_height * new_width, sizeof(short))) == NULL ) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile->max_el = -32768;
|
||||||
|
tile->min_el = 32768;
|
||||||
|
|
||||||
|
/* Making the tile data smaller */
|
||||||
|
if (scale < 1) {
|
||||||
|
skip_count = 1 / scale;
|
||||||
|
} else {
|
||||||
|
copy_count = (size_t) scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
fprintf(stderr,"Resampling tile %s [%.1f]:\n\tOld %dx%d. New %zux%zu\n\tScale %f Skip %zu Copy %zu\n", tile->filename, tile->resolution, tile->width, tile->height, new_width, new_height, scale, skip_count, copy_count);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
/* Nearest neighbour normalization. For each subsample of the original, simply
|
||||||
|
* assign the value in the top left to the new pixel
|
||||||
|
* SOURCE: X / Y
|
||||||
|
* DEST: I / J */
|
||||||
|
|
||||||
|
for (size_t y = 0, j = 0; y < (unsigned)tile->height && j < new_height; y += skip_count, j += copy_count) {
|
||||||
|
|
||||||
|
for (size_t x = 0, i = 0; x < (unsigned)tile->width && i < new_width; x += skip_count, i += copy_count) {
|
||||||
|
|
||||||
|
/* These are for scaling up the data */
|
||||||
|
for (size_t copy_y = 0; copy_y < copy_count; copy_y++) {
|
||||||
|
for (size_t copy_x = 0; copy_x < copy_count; copy_x++) {
|
||||||
|
size_t new_j = j + copy_y;
|
||||||
|
size_t new_i = i + copy_x;
|
||||||
|
/* Do the copy */
|
||||||
|
new_data[ new_j * new_width + new_i ] = tile->data[y * tile->width + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update local min / max values */
|
||||||
|
if (tile->data[y * tile->width + x] > tile->max_el)
|
||||||
|
tile->max_el = tile->data[y * tile->width + x];
|
||||||
|
if (tile->data[y * tile->width + x] < tile->min_el)
|
||||||
|
tile->min_el = tile->data[y * tile->width + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the date in the tile */
|
||||||
|
free(tile->data);
|
||||||
|
tile->data = new_data;
|
||||||
|
|
||||||
|
/* Update the height and width values */
|
||||||
|
tile->height = new_height;
|
||||||
|
tile->width = new_width;
|
||||||
|
tile->resolution *= 1/scale; // A scale of 2 is HALF the resolution
|
||||||
|
tile->ppdx = tile->width / tile->width_deg;
|
||||||
|
tile->ppdy = tile->height / tile->height_deg;
|
||||||
|
// tile->width_deg *= scale;
|
||||||
|
// tile->height_deg *= scale;
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Resampling complete. New resolution: %.1f\n", tile->resolution);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tile_resize
|
||||||
|
* This function works in conjuntion with resample_data. It takes a
|
||||||
|
* resolution value in meters as its argument. It then calculates the
|
||||||
|
* nearest (via averaging) resample value and calls resample_data
|
||||||
|
*/
|
||||||
|
int tile_resize(tile_t* tile, int resolution){
|
||||||
|
double current_res_km = haversine_formula(tile->max_north, tile->max_west, tile->max_north, tile->min_west);
|
||||||
|
int current_res = (int) ceil((current_res_km/IPPD)*1000);
|
||||||
|
float scaling_factor = resolution / current_res;
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Resampling: Current %dm Desired %dm Scale %.1f\n", current_res, resolution, scaling_factor);
|
||||||
|
return tile_rescale(tile, scaling_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tile_destroy
|
||||||
|
* This function simply destroys any data associated with a tile
|
||||||
|
*/
|
||||||
|
void tile_destroy(tile_t* tile){
|
||||||
|
if (tile->data != NULL)
|
||||||
|
free(tile->data);
|
||||||
|
}
|
||||||
|
|
48
src/tiles.hh
Normal file
48
src/tiles.hh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef _TILES_HH_
|
||||||
|
#define _TILES_HH_
|
||||||
|
|
||||||
|
typedef struct _tile_t{
|
||||||
|
char *filename;
|
||||||
|
union{
|
||||||
|
int cols;
|
||||||
|
int width;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
int rows;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
double xll;
|
||||||
|
double max_west;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
double yll;
|
||||||
|
double min_north;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
double xur;
|
||||||
|
double min_west;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
double yur;
|
||||||
|
double max_north;
|
||||||
|
};
|
||||||
|
double cellsize;
|
||||||
|
long long datastart;
|
||||||
|
short nodata;
|
||||||
|
short max_el;
|
||||||
|
short min_el;
|
||||||
|
short *data;
|
||||||
|
float precise_resolution;
|
||||||
|
float resolution;
|
||||||
|
double width_deg;
|
||||||
|
double height_deg;
|
||||||
|
int ppdx;
|
||||||
|
int ppdy;
|
||||||
|
} tile_t, *ptile_t;
|
||||||
|
|
||||||
|
int tile_load_lidar(tile_t*, char *);
|
||||||
|
int tile_rescale(tile_t *, float);
|
||||||
|
void tile_destroy(tile_t *);
|
||||||
|
|
||||||
|
#endif
|
42
test.sh
Executable file
42
test.sh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
mkdir tests
|
||||||
|
RAD=5
|
||||||
|
MAXRAD=50
|
||||||
|
FRQ=446
|
||||||
|
ERP=25
|
||||||
|
|
||||||
|
echo "Running 50cm LIDAR test..."
|
||||||
|
./signalserverLIDAR -lid data/sk3587_50cm.asc -lat 53.383 -lon -1.468 -txh 8 -f $FRQ -erp 1 -rxh 2 -m -dbm -rt -90 -o tests/1 -R 0.5 -t
|
||||||
|
echo "Converting to PNG..."
|
||||||
|
convert tests/1.ppm -transparent white -channel Alpha PNG32:tests/1.png
|
||||||
|
rm tests/1.ppm
|
||||||
|
rm tests/1.*cf
|
||||||
|
|
||||||
|
echo "Running 30m Meridian test..."
|
||||||
|
./signalserverLIDAR -lid data/N051E000_AVE_DSM.tif.asc,data/N051W001_AVE_DSM.tif.asc -lat 51.472 -lon 0.0096 -txh 12 -f $FRQ -erp 5 -rxh 2 -m -dbm -rt -100 -o tests/2 -R 10 -t
|
||||||
|
echo "Converting to PNG..."
|
||||||
|
convert tests/2.ppm -transparent white -channel Alpha PNG32:tests/2.png
|
||||||
|
rm tests/2.ppm
|
||||||
|
rm tests/2.*cf
|
||||||
|
|
||||||
|
echo "Running 446 Mhz Antenna and UDT Clutter test..."
|
||||||
|
./signalserver -sdf /mnt/data -lat 42.328889 -lon -87.862500 -txh 300 -rxh 2 -f $FRQ -erp 700 -R 50 -res 600 -rt 39 -ant antenna/DB413-B -rot 180 -udt data/test.udt -pm 1 -t -o tests/ant-udt_test
|
||||||
|
convert tests/ant-udt_test.ppm tests/ant-udt_test.png
|
||||||
|
rm tests/ant-udt_test.ppm
|
||||||
|
rm tests/ant-udt_test.*cf
|
||||||
|
|
||||||
|
echo "Running soak test out to $MAXRAD"
|
||||||
|
while [ $RAD -lt $MAXRAD ]; do
|
||||||
|
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius..."
|
||||||
|
time ./signalserver -m -sdf data -lat 51.5 -lon -0.50 -txh 15 -rxh 2 -m -dbm -rt -100 -R $RAD -erp $ERP -f $FRQ -o tests/$RAD -pm 1 -res 1200 -t
|
||||||
|
convert tests/$RAD.ppm tests/$RAD.png
|
||||||
|
rm tests/$RAD.ppm
|
||||||
|
rm tests/$RAD.*cf
|
||||||
|
|
||||||
|
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius (HD mode)..."
|
||||||
|
time ./signalserverHD -m -sdf data -lat 51.5 -lon -0.50 -txh 15 -rxh 2 -m -dbm -rt -100 -R $RAD -erp $ERP -f $FRQ -o tests/$RAD.hd -pm 1 -res 3600 -t
|
||||||
|
convert tests/$RAD.hd.ppm tests/$RAD.hd.png
|
||||||
|
rm tests/$RAD.hd.ppm
|
||||||
|
rm tests/$RAD.*cf
|
||||||
|
let RAD=RAD+5
|
||||||
|
done
|
15
utils/antenna/README.md
Normal file
15
utils/antenna/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Utility for convertng .ant files to Signal Server Format
|
||||||
|
|
||||||
|
ant2azel
|
||||||
|
|
||||||
|
-i antfilenam
|
||||||
|
-o outputfile
|
||||||
|
|
||||||
|
|
||||||
|
-d enable debugging
|
||||||
|
-h print help
|
||||||
|
|
||||||
|
-a Set the azimuth of the antenna
|
||||||
|
-t Set the mechanical tilt of the antenna positive numbers are downtilt.
|
||||||
|
|
||||||
|
orginal version by kd7lxl, adapted to include the azimuth and tilt
|
64
utils/antenna/ant2azel.py
Executable file
64
utils/antenna/ant2azel.py
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import sys
|
||||||
|
import getopt
|
||||||
|
import os.path
|
||||||
|
from os.path import splitext
|
||||||
|
|
||||||
|
|
||||||
|
def db_to_norm(db):
|
||||||
|
return 10**(db/10.)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
antfile = ''
|
||||||
|
outfile = ''
|
||||||
|
direction = 0
|
||||||
|
tilt = 0
|
||||||
|
debug = 0
|
||||||
|
program = os.path.basename(__file__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(argv,"dha:i:o:t:",["debug","help","azimuth=","infile=","outfile=","tilt="])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print program + ' --debug --help -a <azimuth> -t <mechanicaldowntilt> -i <inputfile> -o <outputfile>'
|
||||||
|
sys.exit(2)
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt in ("-d", "--debug"):
|
||||||
|
debug = 1
|
||||||
|
elif opt in ("-h", "--help"):
|
||||||
|
print program + ' --debug --help -a <azimuth> -t <mechanicaldowntilt> -i <inputfile> -o <outputfile>'
|
||||||
|
sys.exit(2)
|
||||||
|
elif opt in ("-i", "--infile"):
|
||||||
|
antfile = arg
|
||||||
|
elif opt in ("-o", "--outfile"):
|
||||||
|
outfile = arg
|
||||||
|
elif opt in ("-a", "--azimuth"):
|
||||||
|
direction = arg
|
||||||
|
elif opt in ("-t", "--tilt"):
|
||||||
|
tilt = arg
|
||||||
|
if antfile == '':
|
||||||
|
print program + ' --debug --help -a <azimuth> -t <mechanicaldowntilt> -i <inputfile> -o <outputfile>'
|
||||||
|
sys.exit(2)
|
||||||
|
if outfile == '' :
|
||||||
|
outfile = splitext(antfile)[0]
|
||||||
|
if debug :
|
||||||
|
print "outfile " + outfile
|
||||||
|
print "downtilt " + tilt
|
||||||
|
with open(antfile, 'r') as ant:
|
||||||
|
with open(outfile + '.az', 'w') as az:
|
||||||
|
# azimuth offset as provided by command arg or 0
|
||||||
|
az.write("%d\n" % float(direction))
|
||||||
|
# Read the first 360 lines of the file
|
||||||
|
for i in xrange(360):
|
||||||
|
az.write("%d\t%0.4f\n" % (i, db_to_norm(float(next(ant)))))
|
||||||
|
with open(outfile + '.el', 'w') as el:
|
||||||
|
# mechanical downtilt, azimuth of tilt
|
||||||
|
el.write("%0.1f\t%0.1f\n" % (float(tilt), float(direction)))
|
||||||
|
# Read the lines for elevations +10 through -90).
|
||||||
|
# The rest of the .ant is unused.
|
||||||
|
for i, line in enumerate(list(ant)[80:181], -10):
|
||||||
|
el.write("%d\t%0.4f\n" % (i, db_to_norm(float(line))))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[1:])
|
73
utils/geoTiff/geotiff2geojson.sh
Executable file
73
utils/geoTiff/geotiff2geojson.sh
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Requires:
|
||||||
|
# - gdal_sieve.py
|
||||||
|
# - ogr2ogr (GDAL)
|
||||||
|
# - topojson (node.js)
|
||||||
|
# obtained from: https://gist.github.com/petesaia
|
||||||
|
|
||||||
|
# Grab the relative directory for source file.
|
||||||
|
SRC_DIR=`dirname $1`
|
||||||
|
|
||||||
|
# Which raster to compress.
|
||||||
|
ORG_FILE="$1"
|
||||||
|
ADD_COL="$2"
|
||||||
|
|
||||||
|
# Final output file.
|
||||||
|
OUTPUT_FILE="$1.json"
|
||||||
|
|
||||||
|
echo "Processing $ORG_FILE."
|
||||||
|
|
||||||
|
# Where to output the new file.
|
||||||
|
TMP_DIR=$SRC_DIR/tmp
|
||||||
|
|
||||||
|
# The amount of times the file should be passed over.
|
||||||
|
ITERATIONS=4
|
||||||
|
|
||||||
|
# Threshold for each iteration.
|
||||||
|
THRESHOLD=40
|
||||||
|
|
||||||
|
# TopoJSON area threshold for simplification.
|
||||||
|
TOPO_COMPRESSION=0.0001
|
||||||
|
|
||||||
|
# Setup internal vars.
|
||||||
|
_CUR=$THRESHOLD
|
||||||
|
_COMPRESSION=$(($ITERATIONS * $THRESHOLD))
|
||||||
|
|
||||||
|
#rm -rf $TMP_DIR
|
||||||
|
mkdir -p $TMP_DIR
|
||||||
|
|
||||||
|
# Start sieve passes.
|
||||||
|
gdal_sieve.py -st $THRESHOLD -4 $ORG_FILE $TMP_DIR/output-"$THRESHOLD".tiff
|
||||||
|
|
||||||
|
while [ $_CUR -le $_COMPRESSION ]; do
|
||||||
|
let _PREV=$_CUR
|
||||||
|
let _CUR=$_CUR+$THRESHOLD
|
||||||
|
echo "Compressing output-$_PREV.tiff into $_CUR.tiff"
|
||||||
|
gdal_sieve.py -st $THRESHOLD -4 "$TMP_DIR/output-$_PREV.tiff" \
|
||||||
|
"$TMP_DIR/output-$_CUR.tiff"
|
||||||
|
rm "$TMP_DIR/output-$_PREV.tiff"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Raster to vector.
|
||||||
|
gdal_polygonize.py $TMP_DIR/output-"$_CUR".tiff \
|
||||||
|
-f "ESRI Shapefile" $TMP_DIR vector n
|
||||||
|
|
||||||
|
if [ ! -z "$ADD_COL" ]; then
|
||||||
|
echo "Adding $ADDCOL information"
|
||||||
|
ogrinfo "$TMP_DIR/vector.shp" -sql "ALTER TABLE vector ADD COLUMN fname character(32)"
|
||||||
|
ogrinfo "$TMP_DIR/vector.shp" -dialect SQLite -sql "UPDATE vector SET fname ='$ADD_COL'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Change shapefile to geojson without the 0 layer, which is water. and simply to ~ 100m resolution
|
||||||
|
echo "Change shapefile to geojson without the 0 layer, which is water."
|
||||||
|
# and simply to ~ 100m resolution
|
||||||
|
# ogr2ogr -f "GeoJSON" -where "n != 0" "$TMP_DIR/geojson.json" "$TMP_DIR/vector.shp"
|
||||||
|
ogr2ogr -f "GeoJSON" "$TMP_DIR/geojson.json" "$TMP_DIR/vector.shp"
|
||||||
|
# Convert to compressed TopoJSON.
|
||||||
|
# topojson -o $OUTPUT_FILE --no-stitch-poles -s $TOPO_COMPRESSION \
|
||||||
|
# -p -- "$TMP_DIR/geojson.json"
|
||||||
|
|
||||||
|
# Clean up.
|
||||||
|
#rm -rf $TMP_DIR
|
21
utils/lidar/README.md
Normal file
21
utils/lidar/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Format used by Signal-Server for LIDAR is as follows:
|
||||||
|
|
||||||
|
GDAL Driver AAIGrid
|
||||||
|
Type Int32
|
||||||
|
|
||||||
|
Projection EPSG:4326
|
||||||
|
|
||||||
|
Pacific Northwest LIDAR comes in esri .e00 format. To get it into a usable form
|
||||||
|
we can use gdal tools.
|
||||||
|
|
||||||
|
Reproject the source data to EPSG:4326 (GRS84, lat/long)
|
||||||
|
gdalwarp -t_srs EPSG:4326 -of GS7BG -ot Float64 srcfile.e00 destfile.xyz
|
||||||
|
|
||||||
|
[user@host ~]$ gdalwarp -t_srs EPSG:4326 -of GS7BG -ot Float64 ~/q47122a71.e00 ~/q47122a71.xyz
|
||||||
|
|
||||||
|
Convert the intermedatry file to AAIGrid Int32
|
||||||
|
gdal_translate -of AAIGrid -ot Int32 srcfile.xyz destfile.asc
|
||||||
|
|
||||||
|
[user@host ~]$ gdal_translate -of AAIGrid -ot Int32 ~/q47122a71.xyz ~/q47122a71.asc
|
||||||
|
|
||||||
|
The above could be pipelined to reduce intermedaty files.
|
131
utils/sdf/README.md
Normal file
131
utils/sdf/README.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
================
|
||||||
|
SPLAT! Utilities
|
||||||
|
================
|
||||||
|
|
||||||
|
Utilities for use with SPLAT! software are found under the
|
||||||
|
splat-1.3.0/utils directory. They include the following:
|
||||||
|
|
||||||
|
|
||||||
|
srtm2sdf
|
||||||
|
========
|
||||||
|
The srtm2sdf utility generates Data Files (SDFs) for use with Signal-Server
|
||||||
|
from STS-99 Space Shuttle Topography Mission (SRTM) elevation data files.
|
||||||
|
This data is of a much higher quality than that contained in older USGS
|
||||||
|
Digital Elevation Models of the same resolution. However, many SRTM
|
||||||
|
Version 2 elevation models contain data "spikes", "voids", and "wells"
|
||||||
|
that are the consequence of the radar mapping process.
|
||||||
|
|
||||||
|
The srtm2sdf utility has the ability to detect and replace SRTM data
|
||||||
|
outliers with equivalent usgs2sdf derived SDF data (see usgs2sdf below).
|
||||||
|
If such data is not available, SRTM outliers are handled either through
|
||||||
|
adjacent pixel averaging, or by threshold limiting using user-specified
|
||||||
|
limits. Of all three methods, the USGS-derived SDF replacement method
|
||||||
|
yields the best results.
|
||||||
|
|
||||||
|
The srtm2sdf utility processes SRTM-3 3-arc second resolution data
|
||||||
|
or use with Signal-Server operating in standard definition mode.
|
||||||
|
|
||||||
|
SRTM-3 Version 2 Elevation Data files may be downloaded from:
|
||||||
|
|
||||||
|
ftp://e0srp01u.ecs.nasa.gov:21/srtm/version2/
|
||||||
|
|
||||||
|
Files available at this site are ZIP compressed, and must be
|
||||||
|
uncompressed (using "unzip", or "gunzip -S .zip") prior to being
|
||||||
|
processed by srtm2sdf.
|
||||||
|
|
||||||
|
The srtm2sdf utility accepts command-line options as follows:
|
||||||
|
|
||||||
|
-d: used to specify the directory path to the location of usgs2sdf
|
||||||
|
derived SDF files that are to be used to replace outliers found
|
||||||
|
in the SRTM data file. The -d option overrides the default path
|
||||||
|
specified in your $HOME/.splat_path file.
|
||||||
|
|
||||||
|
-n: used to specify the elevation (in meters) below which SRTM data
|
||||||
|
is either replaced with usgs2sdf-derived SDF data, or averaged
|
||||||
|
among adjacent elevation data points. The default threshold for
|
||||||
|
the replacement limit is sea-level (0 meters). Unless elevations
|
||||||
|
below sea-level are known to exist for the region being
|
||||||
|
processed by the srtm2sdf utility, the -n option need not be
|
||||||
|
specified.
|
||||||
|
|
||||||
|
Some examples of srtm2sdf use:
|
||||||
|
|
||||||
|
srtm2sdf N40W074.hgt
|
||||||
|
|
||||||
|
srtm2sdf -d /cdrom/sdf N40W074.hgt
|
||||||
|
|
||||||
|
srtm2sdf -d /dev/null N40W074.hgt (/dev/null prevents USGS data
|
||||||
|
replacement from taking place)
|
||||||
|
|
||||||
|
srtm2sdf -n -5 N40W074.hgt
|
||||||
|
|
||||||
|
In all cases, SDF files are written into the current working directory.
|
||||||
|
|
||||||
|
The srtm2sdf utility may also be used to convert 3-arc second SRTM data
|
||||||
|
in Band Interleaved by Line (.BIL) format for use with SPLAT! This data
|
||||||
|
is available via the web at: http://seamless.usgs.gov/website/seamless/
|
||||||
|
|
||||||
|
Once the region of the world has been selected at this site, select the
|
||||||
|
"Define Download Area By Coordinates" button under "Downloads". Proceed
|
||||||
|
to request the download of the region(s) desired in 1 degree by 1 degree
|
||||||
|
regions only, and make sure bounding coordinates entered fall exactly on
|
||||||
|
whole numbers of latitude and longitude (no decimal fractions of a degree).
|
||||||
|
|
||||||
|
Select the "Add Area" button at the bottom.
|
||||||
|
|
||||||
|
On the next screen, select "Modify Data Request". On the subsequent screen,
|
||||||
|
de-select the National Elevation Dataset (NED) format and select "SRTM 3 arc
|
||||||
|
sec - Shuttle Radar Topography Mission [Finished]". Change the format from
|
||||||
|
ArcGrid to BIL, and from HTML to TXT.
|
||||||
|
|
||||||
|
Select the "Save Changes and Return To Summary" button.
|
||||||
|
|
||||||
|
Select the "Download" button, and save the file once it has been sent to
|
||||||
|
your web browser.
|
||||||
|
|
||||||
|
Uncompressing the file will generate a directory containing all files
|
||||||
|
contained within the downloaded archive. Move into the directory and
|
||||||
|
invoke srtm2sdf as described above with the filename having the .bil
|
||||||
|
extension given as its argument. Finally, move or copy the generated
|
||||||
|
.sdf file to your SPLAT! working directory.
|
||||||
|
|
||||||
|
|
||||||
|
srtm2sdf-hd
|
||||||
|
===========
|
||||||
|
The srtm2sdf-hd utility operates in an identical manner as srtm2sdf,
|
||||||
|
but is used to generate HD SDF files from SRTM-1 one-arc second
|
||||||
|
resolution data files for use with signalserverHD. SRTM-1 data files
|
||||||
|
are available for the United States and its territories and
|
||||||
|
possessions, and may be downloaded from:
|
||||||
|
|
||||||
|
ftp://e0srp01u.ecs.nasa.gov:21/srtm/version2/SRTM1/
|
||||||
|
|
||||||
|
|
||||||
|
usgs2sdf
|
||||||
|
========
|
||||||
|
The usgs2sdf utility takes as an argument the name of an uncompressed
|
||||||
|
and record delimited Digital Elevation Model Data (DEM) downloaded from
|
||||||
|
the US Geological Survey, and generates a SPLAT Data File (SDF) compatible
|
||||||
|
with signalserver. usgs2sdf may be invoked manually, or via the
|
||||||
|
postdownload.sh script.
|
||||||
|
|
||||||
|
|
||||||
|
postdownload.sh
|
||||||
|
===============
|
||||||
|
postdownload.sh is a front-end to the usgs2sdf utility. postdownload.sh
|
||||||
|
takes as an argument the name of the gzipped Digital Elevation Model
|
||||||
|
(DEM) downloaded from the US Geological Survey (ie: wilmington-w.gz).
|
||||||
|
postdownload.sh uncompresses the DEM file, adds necessary record delimiters,
|
||||||
|
and invokes usgs2sdf to produce a SPLAT! Data File (SDF).
|
||||||
|
|
||||||
|
USGS Digital Elevation Models may be downloaded from:
|
||||||
|
|
||||||
|
http://edcftp.cr.usgs.gov/pub/data/DEM/250/
|
||||||
|
|
||||||
|
Invoke postdownload with the name of each DEM file downloaded to
|
||||||
|
produce a database of SPLAT Data Files.
|
||||||
|
|
||||||
|
---
|
||||||
|
John A. Magliacane, KD2BD
|
||||||
|
August 2008
|
||||||
|
|
59
utils/sdf/build
Executable file
59
utils/sdf/build
Executable file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Simple shell script for building SPLAT! and associated utilities.
|
||||||
|
# Written by John A. Magliacane, KD2BD May 2002. Updated September 2009.
|
||||||
|
#
|
||||||
|
|
||||||
|
build_usgs2sdf()
|
||||||
|
{
|
||||||
|
echo -n "Compiling usgs2sdf... "
|
||||||
|
cc -Wall -O2 -fomit-frame-pointer usgs2sdf.c -o usgs2sdf
|
||||||
|
|
||||||
|
if [ -x usgs2sdf ]; then
|
||||||
|
echo "Done!"
|
||||||
|
else
|
||||||
|
echo "Compilation failed!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
build_srtm2sdf()
|
||||||
|
{
|
||||||
|
echo -n "Compiling srtm2sdf... "
|
||||||
|
cc -Wall -O2 -fomit-frame-pointer srtm2sdf.c -lbz2 -o srtm2sdf
|
||||||
|
rm -f srtm2sdf-hd
|
||||||
|
ln -s srtm2sdf srtm2sdf-hd
|
||||||
|
|
||||||
|
if [ -x srtm2sdf ]; then
|
||||||
|
echo "Done!"
|
||||||
|
else
|
||||||
|
echo "Compilation failed!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$#" = "0" ]; then
|
||||||
|
echo "Usage: build { srtm2sdf, usgs2sdf, all }"
|
||||||
|
else
|
||||||
|
if [ "$1" = "usgs2sdf" ]; then
|
||||||
|
build_usgs2sdf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "srtm2sdf" ]; then
|
||||||
|
build_srtm2sdf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "clean" ]; then
|
||||||
|
rm -f usgs2sdf srtm2sdf srtm2sdf-hd
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "all" ]; then
|
||||||
|
build_usgs2sdf
|
||||||
|
build_srtm2sdf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" != "citydecoder" ] && [ "$1" != "srtm2sdf" ] && [ "$1" != "usgs2sdf" ] && [ "$1" != "fontdata" ] && [ "$1" != "bearing" ] && [ "$1" != "clean" ] && [ "$1" != "all" ]; then
|
||||||
|
echo "Usage: build { srtm2sdf, usgs2sdf, all }"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
4
utils/sdf/convert_sdf.sh
Executable file
4
utils/sdf/convert_sdf.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
for file in *hgt
|
||||||
|
do
|
||||||
|
sudo ./srtm2sdf -d /dev/null $file
|
||||||
|
done
|
4
utils/sdf/convert_sdf_hd.sh
Executable file
4
utils/sdf/convert_sdf_hd.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
for file in *hgt
|
||||||
|
do
|
||||||
|
sudo ./srtm2sdf-hd -d /dev/null $file
|
||||||
|
done
|
33
utils/sdf/postdownload.sh
Executable file
33
utils/sdf/postdownload.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Simple script for processing of downloaded undelimited gzipped
|
||||||
|
# USGS DEM files, and converting them to SPLAT Data Files.
|
||||||
|
# Written by John A. Magliacane, KD2BD May 2002.
|
||||||
|
# Last modified on Sunday 01-Mar-09.
|
||||||
|
|
||||||
|
if [ "$#" = "0" ]; then
|
||||||
|
echo
|
||||||
|
echo "This utility reads downloaded gzipped USGS DEM"
|
||||||
|
echo "files and generates equivalent SPLAT Data Files (SDFs)."
|
||||||
|
echo
|
||||||
|
echo "Files compatible with this SPLAT! utility may be"
|
||||||
|
echo "obtained at:"
|
||||||
|
echo
|
||||||
|
echo "http://edcftp.cr.usgs.gov/pub/data/DEM/250/"
|
||||||
|
echo
|
||||||
|
echo "Usage: postdownload.sh wilmington-w.gz"
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
# gunzip the downloaded file...
|
||||||
|
echo -n "Uncompressing $1..."
|
||||||
|
gunzip -c $1 > unzipped_file
|
||||||
|
echo
|
||||||
|
echo "Adding record delimiters..."
|
||||||
|
dd if=unzipped_file of=delimited_file ibs=4096 cbs=1024 conv=unblock
|
||||||
|
# Invoke usgs2sdf to generate a SPLAT Data File...
|
||||||
|
usgs2sdf delimited_file
|
||||||
|
echo -n "Removing temp files..."
|
||||||
|
rm delimited_file unzipped_file
|
||||||
|
echo
|
||||||
|
echo "Done!"
|
||||||
|
fi
|
722
utils/sdf/srtm2sdf.c
Normal file
722
utils/sdf/srtm2sdf.c
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
/**************************************************************\
|
||||||
|
** Created originally by Jonathan Naylor, G4KLX. **
|
||||||
|
** Later embellished by John Magliacane, KD2BD to **
|
||||||
|
** detect and handle voids found in the SRTM data, **
|
||||||
|
** SRTM-3 data in .BIL and .HGT format, and high **
|
||||||
|
** resolution SRTM-1 one arc-second topography data. **
|
||||||
|
**************************************************************
|
||||||
|
** Compile like this: **
|
||||||
|
** cc -Wall -O3 -s -lbz2 srtm2sdf.c -o srtm2sdf **
|
||||||
|
** Last modification: 20-Jan-2011 **
|
||||||
|
\**************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <bzlib.h>
|
||||||
|
|
||||||
|
#define BZBUFFER 65536
|
||||||
|
|
||||||
|
char sdf_filename[30], sdf_path[255], replacement_flag, opened=0,
|
||||||
|
hgt=0, bil=0;
|
||||||
|
|
||||||
|
int srtm[3601][3601], usgs[1201][1201], max_north, max_west, n,
|
||||||
|
min_north, min_west, merge=0, min_elevation, bzerror, ippd, mpi;
|
||||||
|
|
||||||
|
int ReadSRTM(char *filename)
|
||||||
|
{
|
||||||
|
int x, y, infile, byte=0, bytes_read;
|
||||||
|
unsigned char error, buffer[2];
|
||||||
|
char north[3], west[4], *base=NULL, blw_filename[255];
|
||||||
|
double cell_size, deg_north, deg_west;
|
||||||
|
FILE *fd=NULL;
|
||||||
|
|
||||||
|
if (strstr(filename, ".zip")!=NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: \"%s\" must be uncompressed\n",filename);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(filename, ".tgz")!=NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: \"%s\" must be uncompressed\n",filename);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((strstr(filename, ".hgt")==NULL) && (strstr(filename, ".bil")==NULL))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: \"%s\" does not have the correct extension (.hgt or .bil)\n",filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(filename, ".hgt")!=NULL)
|
||||||
|
hgt=1;
|
||||||
|
|
||||||
|
if (strstr(filename, ".bil")!=NULL)
|
||||||
|
bil=1;
|
||||||
|
|
||||||
|
base=strrchr(filename, '/');
|
||||||
|
|
||||||
|
if (base==NULL)
|
||||||
|
base=filename;
|
||||||
|
else
|
||||||
|
base+=1;
|
||||||
|
|
||||||
|
if (hgt)
|
||||||
|
{
|
||||||
|
/* We obtain coordinates from the base of the .HGT filename */
|
||||||
|
|
||||||
|
north[0]=base[1];
|
||||||
|
north[1]=base[2];
|
||||||
|
north[2]=0;
|
||||||
|
|
||||||
|
west[0]=base[4];
|
||||||
|
west[1]=base[5];
|
||||||
|
west[2]=base[6];
|
||||||
|
west[3]=0;
|
||||||
|
|
||||||
|
if ((base[0]!='N' && base[0]!='S') || (base[3]!='W' && base[3]!='E'))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: \"%s\" doesn't look like a valid .hgt SRTM filename.\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_west=atoi(west);
|
||||||
|
|
||||||
|
if (base[3]=='E')
|
||||||
|
max_west=360-max_west;
|
||||||
|
|
||||||
|
min_west=max_west-1;
|
||||||
|
|
||||||
|
if (max_west==360)
|
||||||
|
max_west=0;
|
||||||
|
|
||||||
|
if (base[0]=='N')
|
||||||
|
min_north=atoi(north);
|
||||||
|
else
|
||||||
|
min_north=-atoi(north);
|
||||||
|
|
||||||
|
max_north=min_north+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bil)
|
||||||
|
{
|
||||||
|
/* We obtain .BIL file coordinates
|
||||||
|
from the corresponding .BLW file */
|
||||||
|
|
||||||
|
strncpy(blw_filename,filename,250);
|
||||||
|
x=strlen(filename);
|
||||||
|
|
||||||
|
if (x>3)
|
||||||
|
{
|
||||||
|
blw_filename[x-2]='l';
|
||||||
|
blw_filename[x-1]='w';
|
||||||
|
blw_filename[x]=0;
|
||||||
|
|
||||||
|
fd=fopen(blw_filename,"rb");
|
||||||
|
|
||||||
|
if (fd!=NULL)
|
||||||
|
{
|
||||||
|
n=fscanf(fd,"%lf",&cell_size);
|
||||||
|
|
||||||
|
if ((cell_size<0.0008) || (cell_size>0.0009))
|
||||||
|
{
|
||||||
|
printf("\n*** .BIL file's cell size is incompatible with SPLAT!!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
n=fscanf(fd,"%lf",°_west);
|
||||||
|
n=fscanf(fd,"%lf",°_west);
|
||||||
|
n=fscanf(fd,"%lf",°_west);
|
||||||
|
|
||||||
|
n=fscanf(fd,"%lf",°_west);
|
||||||
|
|
||||||
|
n=fscanf(fd,"%lf",°_north);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
min_north=(int)(deg_north);
|
||||||
|
max_north=max_north+1;
|
||||||
|
|
||||||
|
if (deg_west<0.0)
|
||||||
|
deg_west=-deg_west;
|
||||||
|
else
|
||||||
|
deg_west=360.0-deg_west;
|
||||||
|
|
||||||
|
min_west=(int)(deg_west);
|
||||||
|
|
||||||
|
if (min_west==360)
|
||||||
|
min_west=0;
|
||||||
|
|
||||||
|
max_west=min_west+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infile=open(filename, O_RDONLY);
|
||||||
|
|
||||||
|
if (infile==0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: Cannot open \"%s\"\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
n=read(infile,&buffer,2);
|
||||||
|
|
||||||
|
if ((buffer[0]=='P') && (buffer[1]=='K'))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "*** Error: \"%s\" still appears to be compressed!\n",filename);
|
||||||
|
close(infile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(infile,0L,SEEK_SET);
|
||||||
|
|
||||||
|
if (ippd==3600)
|
||||||
|
sprintf(sdf_filename, "%d:%d:%d:%d-hd.sdf", min_north, max_north, min_west, max_west);
|
||||||
|
else
|
||||||
|
sprintf(sdf_filename, "%d:%d:%d:%d.sdf", min_north, max_north, min_west, max_west);
|
||||||
|
|
||||||
|
error=0;
|
||||||
|
replacement_flag=0;
|
||||||
|
|
||||||
|
printf("Reading %s... ", filename);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
for (x=0; (x<=ippd && error==0); x++)
|
||||||
|
for (y=0; (y<=ippd && error==0); y++)
|
||||||
|
{
|
||||||
|
bytes_read=read(infile,&buffer,2);
|
||||||
|
|
||||||
|
if (bytes_read==2)
|
||||||
|
{
|
||||||
|
if (bil)
|
||||||
|
{
|
||||||
|
/* "little-endian" structure */
|
||||||
|
|
||||||
|
byte=buffer[0]+(buffer[1]<<8);
|
||||||
|
|
||||||
|
if (buffer[1]&128)
|
||||||
|
byte-=0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hgt)
|
||||||
|
{
|
||||||
|
/* "big-endian" structure */
|
||||||
|
|
||||||
|
byte=buffer[1]+(buffer[0]<<8);
|
||||||
|
|
||||||
|
if (buffer[0]&128)
|
||||||
|
byte-=0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flag problem elevations here */
|
||||||
|
|
||||||
|
if (byte<-32768)
|
||||||
|
byte=-32768;
|
||||||
|
|
||||||
|
if (byte>32767)
|
||||||
|
byte=32767;
|
||||||
|
|
||||||
|
if (byte<=min_elevation)
|
||||||
|
replacement_flag=1;
|
||||||
|
|
||||||
|
srtm[x][y]=byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
error=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n*** Error: Premature EOF detected while reading \"%s\"! :-(\n",filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(infile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoadSDF_SDF(char *name)
|
||||||
|
{
|
||||||
|
/* This function reads uncompressed
|
||||||
|
SPLAT Data Files (.sdf) into memory. */
|
||||||
|
|
||||||
|
int x, y, n, dummy;
|
||||||
|
char sdf_file[255], path_plus_name[512];
|
||||||
|
FILE *infile;
|
||||||
|
|
||||||
|
for (x=0; name[x]!='.' && name[x]!=0 && x<250; x++)
|
||||||
|
sdf_file[x]=name[x];
|
||||||
|
|
||||||
|
sdf_file[x]='.';
|
||||||
|
sdf_file[x+1]='s';
|
||||||
|
sdf_file[x+2]='d';
|
||||||
|
sdf_file[x+3]='f';
|
||||||
|
sdf_file[x+4]=0;
|
||||||
|
|
||||||
|
strncpy(path_plus_name,sdf_path,255);
|
||||||
|
strncat(path_plus_name,sdf_file,254);
|
||||||
|
|
||||||
|
infile=fopen(path_plus_name,"rb");
|
||||||
|
|
||||||
|
if (infile==NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n=fscanf(infile,"%d", &dummy);
|
||||||
|
n=fscanf(infile,"%d", &dummy);
|
||||||
|
n=fscanf(infile,"%d", &dummy);
|
||||||
|
n=fscanf(infile,"%d", &dummy);
|
||||||
|
|
||||||
|
printf("\nReading %s... ",path_plus_name);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
for (x=0; x<1200; x++)
|
||||||
|
for (y=0; y<1200; y++)
|
||||||
|
n=fscanf(infile,"%d",&usgs[x][y]);
|
||||||
|
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *BZfgets(BZFILE *bzfd, unsigned length)
|
||||||
|
{
|
||||||
|
/* This function returns at most one less than 'length' number
|
||||||
|
of characters from a bz2 compressed file whose file descriptor
|
||||||
|
is pointed to by *bzfd. In operation, a buffer is filled with
|
||||||
|
uncompressed data (size = BZBUFFER), which is then parsed
|
||||||
|
and doled out as NULL terminated character strings every time
|
||||||
|
this function is invoked. A NULL string indicates an EOF
|
||||||
|
or error condition. */
|
||||||
|
|
||||||
|
static int x, y, nBuf;
|
||||||
|
static char buffer[BZBUFFER+1], output[BZBUFFER+1];
|
||||||
|
char done=0;
|
||||||
|
|
||||||
|
if (opened!=1 && bzerror==BZ_OK)
|
||||||
|
{
|
||||||
|
/* First time through. Initialize everything! */
|
||||||
|
|
||||||
|
x=0;
|
||||||
|
y=0;
|
||||||
|
nBuf=0;
|
||||||
|
opened=1;
|
||||||
|
output[0]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (x==nBuf && bzerror!=BZ_STREAM_END && bzerror==BZ_OK && opened)
|
||||||
|
{
|
||||||
|
/* Uncompress data into a static buffer */
|
||||||
|
|
||||||
|
nBuf=BZ2_bzRead(&bzerror, bzfd, buffer, BZBUFFER);
|
||||||
|
buffer[nBuf]=0;
|
||||||
|
x=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a string from buffer contents */
|
||||||
|
|
||||||
|
output[y]=buffer[x];
|
||||||
|
|
||||||
|
if (output[y]=='\n' || output[y]==0 || y==(int)length-1)
|
||||||
|
{
|
||||||
|
output[y+1]=0;
|
||||||
|
done=1;
|
||||||
|
y=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
y++;
|
||||||
|
x++;
|
||||||
|
|
||||||
|
} while (done==0);
|
||||||
|
|
||||||
|
if (output[0]==0)
|
||||||
|
opened=0;
|
||||||
|
|
||||||
|
return (output);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoadSDF_BZ(char *name)
|
||||||
|
{
|
||||||
|
/* This function reads .bz2 compressed
|
||||||
|
SPLAT Data Files into memory. */
|
||||||
|
|
||||||
|
int x, y, dummy;
|
||||||
|
char sdf_file[255], path_plus_name[255];
|
||||||
|
FILE *fd;
|
||||||
|
BZFILE *bzfd;
|
||||||
|
|
||||||
|
for (x=0; name[x]!='.' && name[x]!=0 && x<247; x++)
|
||||||
|
sdf_file[x]=name[x];
|
||||||
|
|
||||||
|
sdf_file[x]='.';
|
||||||
|
sdf_file[x+1]='s';
|
||||||
|
sdf_file[x+2]='d';
|
||||||
|
sdf_file[x+3]='f';
|
||||||
|
sdf_file[x+4]='.';
|
||||||
|
sdf_file[x+5]='b';
|
||||||
|
sdf_file[x+6]='z';
|
||||||
|
sdf_file[x+7]='2';
|
||||||
|
sdf_file[x+8]=0;
|
||||||
|
|
||||||
|
strncpy(path_plus_name,sdf_path,255);
|
||||||
|
strncat(path_plus_name,sdf_file,254);
|
||||||
|
|
||||||
|
fd=fopen(path_plus_name,"rb");
|
||||||
|
bzfd=BZ2_bzReadOpen(&bzerror,fd,0,0,NULL,0);
|
||||||
|
|
||||||
|
if (fd!=NULL && bzerror==BZ_OK)
|
||||||
|
{
|
||||||
|
printf("\nReading %s... ",path_plus_name);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
sscanf(BZfgets(bzfd,255),"%d",&dummy);
|
||||||
|
sscanf(BZfgets(bzfd,255),"%d",&dummy);
|
||||||
|
sscanf(BZfgets(bzfd,255),"%d",&dummy);
|
||||||
|
sscanf(BZfgets(bzfd,255),"%d",&dummy);
|
||||||
|
|
||||||
|
for (x=0; x<1200; x++)
|
||||||
|
for (y=0; y<1200; y++)
|
||||||
|
sscanf(BZfgets(bzfd,20),"%d",&usgs[x][y]);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
BZ2_bzReadClose(&bzerror,bzfd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char LoadSDF(char *name)
|
||||||
|
{
|
||||||
|
/* This function loads the requested SDF file from the filesystem.
|
||||||
|
First, it tries to invoke the LoadSDF_SDF() function to load an
|
||||||
|
uncompressed SDF file (since uncompressed files load slightly
|
||||||
|
faster). Failing that, it tries to load a compressed SDF file
|
||||||
|
by invoking the LoadSDF_BZ() function. */
|
||||||
|
|
||||||
|
int return_value=-1;
|
||||||
|
|
||||||
|
/* Try to load an uncompressed SDF first. */
|
||||||
|
|
||||||
|
return_value=LoadSDF_SDF(name);
|
||||||
|
|
||||||
|
/* If that fails, try loading a compressed SDF. */
|
||||||
|
|
||||||
|
if (return_value==0 || return_value==-1)
|
||||||
|
return_value=LoadSDF_BZ(name);
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadUSGS()
|
||||||
|
{
|
||||||
|
char usgs_filename[15];
|
||||||
|
|
||||||
|
/* usgs_filename is a minimal filename ("40:41:74:75").
|
||||||
|
Full path and extentions are added later though
|
||||||
|
subsequent function calls. */
|
||||||
|
|
||||||
|
sprintf(usgs_filename, "%d:%d:%d:%d", min_north, max_north, min_west, max_west);
|
||||||
|
|
||||||
|
return (LoadSDF(usgs_filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void average_terrain(y,x,z)
|
||||||
|
int x, y, z;
|
||||||
|
{
|
||||||
|
long accum;
|
||||||
|
int temp=0, count, bad_value;
|
||||||
|
double average;
|
||||||
|
|
||||||
|
bad_value=srtm[y][x];
|
||||||
|
|
||||||
|
accum=0L;
|
||||||
|
count=0;
|
||||||
|
|
||||||
|
if (y>=2)
|
||||||
|
{
|
||||||
|
temp=srtm[y-1][x];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y<=mpi)
|
||||||
|
{
|
||||||
|
temp=srtm[y+1][x];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((y>=2) && (x<=(mpi-1)))
|
||||||
|
{
|
||||||
|
temp=srtm[y-1][x+1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x<=(mpi-1))
|
||||||
|
{
|
||||||
|
temp=srtm[y][x+1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x<=(mpi-1)) && (y<=mpi))
|
||||||
|
{
|
||||||
|
temp=srtm[y+1][x+1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x>=1) && (y>=2))
|
||||||
|
{
|
||||||
|
temp=srtm[y-1][x-1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x>=1)
|
||||||
|
{
|
||||||
|
temp=srtm[y][x-1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((y<=mpi) && (x>=1))
|
||||||
|
{
|
||||||
|
temp=srtm[y+1][x-1];
|
||||||
|
|
||||||
|
if (temp>bad_value)
|
||||||
|
{
|
||||||
|
accum+=temp;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count!=0)
|
||||||
|
{
|
||||||
|
average=(((double)accum)/((double)count));
|
||||||
|
temp=(int)(average+0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp>min_elevation)
|
||||||
|
srtm[y][x]=temp;
|
||||||
|
else
|
||||||
|
srtm[y][x]=min_elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteSDF(char *filename)
|
||||||
|
{
|
||||||
|
/* Like the HGT files, the extreme southwest corner
|
||||||
|
* provides the point of reference for the SDF file.
|
||||||
|
* The SDF file extends from min_north degrees to
|
||||||
|
* the south to min_north+(mpi/ippd) degrees to
|
||||||
|
* the north, and max_west degrees to the west to
|
||||||
|
* max_west-(mpi/ippd) degrees to the east. The
|
||||||
|
* overlapping edge redundancy present in the HGT
|
||||||
|
* and earlier USGS files is not necessary, nor
|
||||||
|
* is it present in SDF files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int x, y, byte, last_good_byte=0;
|
||||||
|
FILE *outfile;
|
||||||
|
|
||||||
|
printf("\nWriting %s... ", filename);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
outfile=fopen(filename,"wb");
|
||||||
|
|
||||||
|
fprintf(outfile, "%d\n%d\n%d\n%d\n", max_west, min_north, min_west, max_north);
|
||||||
|
|
||||||
|
for (y=ippd; y>=1; y--) /* Omit the northern most edge */
|
||||||
|
for (x=mpi; x>=0; x--) /* Omit the eastern most edge */
|
||||||
|
{
|
||||||
|
byte=srtm[y][x];
|
||||||
|
|
||||||
|
if (byte>min_elevation)
|
||||||
|
last_good_byte=byte;
|
||||||
|
|
||||||
|
if (byte<min_elevation)
|
||||||
|
{
|
||||||
|
if (merge)
|
||||||
|
{
|
||||||
|
if (ippd==3600)
|
||||||
|
fprintf(outfile,"%d\n",usgs[1200-(y/3)][1199-(x/3)]);
|
||||||
|
else
|
||||||
|
fprintf(outfile,"%d\n",usgs[1200-y][1199-x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
average_terrain(y,x,last_good_byte);
|
||||||
|
fprintf(outfile,"%d\n",srtm[y][x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(outfile,"%d\n",byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Done!\n");
|
||||||
|
|
||||||
|
fclose(outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int x, y, z=0;
|
||||||
|
char *env=NULL, string[255], *s=NULL;
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
if (strstr(argv[0], "srtm2sdf-hd")!=NULL)
|
||||||
|
{
|
||||||
|
ippd=3600; /* High Definition (1 arc-sec) Mode */
|
||||||
|
strncpy(string,"srtm2sdf-hd\0",12);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ippd=1200; /* Standard Definition (3 arc-sec) Mode */
|
||||||
|
strncpy(string,"srtm2sdf\0",9);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpi=ippd-1; /* Maximum pixel index per degree */
|
||||||
|
|
||||||
|
if (argc==1 || (argc==2 && strncmp(argv[1],"-h",2)==0))
|
||||||
|
{
|
||||||
|
if (ippd==1200)
|
||||||
|
fprintf(stderr, "\nsrtm2sdf: Generates SPLAT! elevation data files from unzipped\nSRTM-3 elevation data files, and replaces SRTM data voids with\nelevation data from older usgs2sdf derived SDF files.\n\n");
|
||||||
|
|
||||||
|
if (ippd==3600)
|
||||||
|
fprintf(stderr, "\nsrtm2sdf-hd: Generates SPLAT! elevation data files from unzipped\nSRTM-1 elevation data files, and replaces SRTM data voids with\naverages, or elevation data from older usgs2sdf derived SDF files.\n\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "\tAvailable Options...\n\n");
|
||||||
|
fprintf(stderr, "\t-d directory path of usgs2sdf derived SDF files\n\t (overrides path in ~/.splat_path file)\n\n");
|
||||||
|
fprintf(stderr, "\t-n elevation limit (in meters) below which SRTM data is\n\t replaced by USGS-derived .sdf data (default = 0 meters)\n\n");
|
||||||
|
fprintf(stderr, "Examples: %s N40W074.hgt\n",string);
|
||||||
|
fprintf(stderr, " %s -d /cdrom/sdf N40W074.hgt\n",string);
|
||||||
|
fprintf(stderr, " %s -d /dev/null N40W074.hgt (prevents data replacement)\n",string);
|
||||||
|
fprintf(stderr, " %s -n -5 N40W074.hgt\n\n",string);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
y=argc-1;
|
||||||
|
|
||||||
|
min_elevation=0;
|
||||||
|
|
||||||
|
for (x=1, z=0; x<=y; x++)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[x],"-d")==0)
|
||||||
|
{
|
||||||
|
z=x+1;
|
||||||
|
|
||||||
|
if (z<=y && argv[z][0] && argv[z][0]!='-')
|
||||||
|
strncpy(sdf_path,argv[z],253);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[x],"-n")==0)
|
||||||
|
{
|
||||||
|
z=x+1;
|
||||||
|
|
||||||
|
if (z<=y && argv[z][0])
|
||||||
|
{
|
||||||
|
sscanf(argv[z],"%d",&min_elevation);
|
||||||
|
|
||||||
|
if (min_elevation<-32767)
|
||||||
|
min_elevation=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no SDF path was specified on the command line (-d), check
|
||||||
|
for a path specified in the $HOME/.splat_path file. If the
|
||||||
|
file is not found, then sdf_path[] remains NULL, and a data
|
||||||
|
merge will not be attempted if voids are found in the SRTM file. */
|
||||||
|
|
||||||
|
if (sdf_path[0]==0)
|
||||||
|
{
|
||||||
|
env=getenv("HOME");
|
||||||
|
|
||||||
|
sprintf(string,"%s/.splat_path",env);
|
||||||
|
|
||||||
|
fd=fopen(string,"r");
|
||||||
|
|
||||||
|
if (fd!=NULL)
|
||||||
|
{
|
||||||
|
s=fgets(string,253,fd);
|
||||||
|
|
||||||
|
/* Remove <CR> and/or <LF> from string */
|
||||||
|
|
||||||
|
for (x=0; string[x]!=13 && string[x]!=10 && string[x]!=0 && x<253; x++);
|
||||||
|
string[x]=0;
|
||||||
|
|
||||||
|
strncpy(sdf_path,string,253);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure a trailing '/' is present in sdf_path */
|
||||||
|
|
||||||
|
if (sdf_path[0])
|
||||||
|
{
|
||||||
|
x=strlen(sdf_path);
|
||||||
|
|
||||||
|
if (sdf_path[x-1]!='/' && x!=0)
|
||||||
|
{
|
||||||
|
sdf_path[x]='/';
|
||||||
|
sdf_path[x+1]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadSRTM(argv[z+1])==0)
|
||||||
|
{
|
||||||
|
if (replacement_flag && sdf_path[0])
|
||||||
|
merge=ReadUSGS();
|
||||||
|
|
||||||
|
WriteSDF(sdf_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
312
utils/sdf/usgs2sdf.c
Normal file
312
utils/sdf/usgs2sdf.c
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* USGS2SDF: USGS to SPLAT Data File Converter Utility *
|
||||||
|
* Copyright John A. Magliacane, KD2BD 1997-2009 *
|
||||||
|
* Last update: 14-Mar-2009 *
|
||||||
|
*****************************************************************************
|
||||||
|
* *
|
||||||
|
* This program reads files containing delimited US Geological Survey *
|
||||||
|
* Digital Elevation Model Data files, and creates Splat Data Files *
|
||||||
|
* containing ONLY the raw information needed by SPLAT!, thereby saving *
|
||||||
|
* disk space, as well as read/write time. *
|
||||||
|
* *
|
||||||
|
* The format of .sdf files created by this utility is as follows: *
|
||||||
|
* *
|
||||||
|
* maximum west longitude (degrees West) *
|
||||||
|
* minimum north latitude (degrees North) *
|
||||||
|
* minimum west longitude (degrees West) *
|
||||||
|
* maximum north latitude (degrees North) *
|
||||||
|
* ...1440000 elevation points... (1200x1200) *
|
||||||
|
* *
|
||||||
|
* All data is represented as integers. A single '\n' follows each value. *
|
||||||
|
* *
|
||||||
|
* SPLAT Data Files are named according to the geographical locations *
|
||||||
|
* they represent (ie: min_north:max_north:min_west:max_west.sdf). *
|
||||||
|
* *
|
||||||
|
*****************************************************************************
|
||||||
|
* To compile: gcc -Wall -O6 -s splat2sdf.c -o splat2sdf *
|
||||||
|
*****************************************************************************
|
||||||
|
* *
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
char *d2e(string)
|
||||||
|
char *string;
|
||||||
|
{
|
||||||
|
/* This function is used to replace 'D's with 'E's for proper
|
||||||
|
exponential notation of numeric strings read from delimited
|
||||||
|
USGS data files. It returns a pointer to a string. */
|
||||||
|
|
||||||
|
unsigned char x;
|
||||||
|
|
||||||
|
for (x=0; string[x]!=0; x++)
|
||||||
|
if (string[x]=='D')
|
||||||
|
string[x]='E';
|
||||||
|
return (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(argc,argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
unsigned char minimum[30], maximum[30], swlong[30], swlat[30],
|
||||||
|
nwlong[30], nwlat[30], nelong[30], nelat[30], selong[30],
|
||||||
|
selat[30];
|
||||||
|
char string[40];
|
||||||
|
double max_el, min_el, max_west, min_west, max_north, min_north;
|
||||||
|
int x, y, z, c, array[1202][1202];
|
||||||
|
char splatfile[25];
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
if (argc!=2)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Usage: usgs2sdf uncompressed_delimited_usgs_datafile (ie: wilmington-e)\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd=fopen(argv[1],"rb");
|
||||||
|
|
||||||
|
if (fd!=NULL)
|
||||||
|
{
|
||||||
|
fprintf(stdout,"Reading \"%s\"...",argv[1]);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Skip first 548 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<548; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read quadrangle corners */
|
||||||
|
|
||||||
|
/* Read southwest longitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
swlong[x]=getc(fd);
|
||||||
|
swlong[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read southwest latitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
swlat[x]=getc(fd);
|
||||||
|
swlat[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read northwest longitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
nwlong[x]=getc(fd);
|
||||||
|
nwlong[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read northwest latitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
nwlat[x]=getc(fd);
|
||||||
|
nwlat[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read northeast longitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
nelong[x]=getc(fd);
|
||||||
|
nelong[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read northeast latitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
nelat[x]=getc(fd);
|
||||||
|
nelat[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read southeast longitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
selong[x]=getc(fd);
|
||||||
|
selong[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read southeast latitude */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
selat[x]=getc(fd);
|
||||||
|
selat[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read minimum elevation */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
minimum[x]=getc(fd);
|
||||||
|
minimum[x]=0;
|
||||||
|
|
||||||
|
/* Skip 2 bytes */
|
||||||
|
|
||||||
|
for (x=0; x<2; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read maximum elevation */
|
||||||
|
|
||||||
|
for (x=0; x<22; x++)
|
||||||
|
maximum[x]=getc(fd);
|
||||||
|
|
||||||
|
maximum[x]=0;
|
||||||
|
|
||||||
|
sscanf(d2e((char*)minimum),"%lG",&min_el);
|
||||||
|
sscanf(d2e((char*)maximum),"%lf",&max_el);
|
||||||
|
|
||||||
|
sscanf(d2e((char*)swlong),"%lf",&max_west);
|
||||||
|
sscanf(d2e((char*)swlat),"%lf",&min_north);
|
||||||
|
|
||||||
|
sscanf(d2e((char*)nelong),"%lf",&min_west);
|
||||||
|
sscanf(d2e((char*)nelat),"%lf",&max_north);
|
||||||
|
|
||||||
|
max_west/=-3600.0;
|
||||||
|
min_north/=3600.0;
|
||||||
|
max_north/=3600.0;
|
||||||
|
min_west/=-3600.0;
|
||||||
|
|
||||||
|
/* Skip 84 Bytes */
|
||||||
|
|
||||||
|
for (x=0; x<84; x++)
|
||||||
|
getc(fd);
|
||||||
|
|
||||||
|
/* Read elevation data... */
|
||||||
|
|
||||||
|
for (x=1200; x>=0; x--)
|
||||||
|
{
|
||||||
|
if (x==900)
|
||||||
|
{
|
||||||
|
printf(" 25%c...",37);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x==600)
|
||||||
|
{
|
||||||
|
printf(" 50%c...",37);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x==300)
|
||||||
|
{
|
||||||
|
printf(" 75%c... ",37);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip over 9 strings of data */
|
||||||
|
|
||||||
|
for (y=0; y<9; y++)
|
||||||
|
{
|
||||||
|
string[0]=0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c=getc(fd);
|
||||||
|
|
||||||
|
} while (c==' ' || c=='\n');
|
||||||
|
|
||||||
|
for (z=0; c!=' ' && c!='\n' && z<28; z++)
|
||||||
|
{
|
||||||
|
string[z]=c;
|
||||||
|
c=getc(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[z]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store elevation data in array */
|
||||||
|
|
||||||
|
for (y=0; y<1201; y++)
|
||||||
|
{
|
||||||
|
string[0]=0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c=getc(fd);
|
||||||
|
|
||||||
|
} while (c==' ' || c=='\n');
|
||||||
|
|
||||||
|
for (z=0; c!=' ' && c!='\n' && z<28; z++)
|
||||||
|
{
|
||||||
|
string[z]=c;
|
||||||
|
c=getc(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
string[z]=0;
|
||||||
|
sscanf(string,"%d",&array[y][x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
/* Write splat data file to disk */
|
||||||
|
|
||||||
|
sprintf(splatfile,"%.0f:%.0f:%.0f:%.0f.sdf",min_north,max_north,min_west,max_west);
|
||||||
|
|
||||||
|
fprintf(stdout," Done!\nWriting \"%s\"... ",splatfile);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
fd=fopen(splatfile,"w");
|
||||||
|
|
||||||
|
fprintf(fd,"%.0f\n%.0f\n%.0f\n%.0f\n", max_west, min_north, min_west, max_north);
|
||||||
|
|
||||||
|
for (x=0; x<1200; x++)
|
||||||
|
for (y=0; y<1200; y++)
|
||||||
|
fprintf(fd,"%d\n",array[x][y]);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
fprintf(stdout,"Done!\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd==NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"*** %c%s%c: File Not Found!\n",34,argv[1],34);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
exit(0);
|
||||||
|
}
|
Reference in New Issue
Block a user