move gbp.conf to debian/
[debian/splat] / splat.cpp
index 8aee28727c97952847e128a904a5205a07d48c13..844a12c3cb7e7822a291ff986847a779c14b1478 100644 (file)
--- a/splat.cpp
+++ b/splat.cpp
@@ -1,30 +1,26 @@
-/****************************************************************************
-*      SPLAT: An RF Signal Propagation Loss and Terrain Analysis Tool       *
-*                        Last update: 15-Mar-2007                          *
-*****************************************************************************
-*           Project started in 1997 by John A. Magliacane, KD2BD           *
-*****************************************************************************
-*                                                                          *
-*     Extensively modified by J. D. McDonald in Jan. 2004 to include        *
-*    the Longley-Rice propagation model using C++ code from NTIA/ITS.      *
-*                                                                          *
-*              See: http://flattop.its.bldrdoc.gov/itm.html                 *
-*                                                                          *
-*****************************************************************************
-*                                                                           *
-* 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.                                                        *
-*                                                                          *
-*****************************************************************************
- g++ -Wall -O3 -s -lm -lbz2 -fomit-frame-pointer itm.cpp splat.cpp -o splat 
-*****************************************************************************/
+/****************************************************************************\
+*         SPLAT!: An RF Signal Path Loss And Terrain Analysis Tool          *
+******************************************************************************
+*           Project started in 1997 by John A. Magliacane, KD2BD            *
+*                        Last update: 10-Apr-2009                           *
+******************************************************************************
+*         Please consult the documentation for a complete list of           *
+*           individuals who have contributed to this project.               *
+******************************************************************************
+*                                                                            *
+*  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.                                                        *
+*                                                                           *
+******************************************************************************
+* g++ -Wall -O3 -s -lm -lbz2 -fomit-frame-pointer itm.cpp splat.cpp -o splat * 
+\****************************************************************************/
 
 #include <stdio.h>
 #include <math.h>
 #include <bzlib.h>
 #include <unistd.h>
 #include "fontdata.h"
-#include "smallfont.h"
+#include "splat.h"
 
 #define GAMMA 2.5
-#define MAXSLOTS 9
 #define BZBUFFER 65536
 
-#if MAXSLOTS==4
-#define ARRAYSIZE 4950
+#if HD_MODE==0
+       #if MAXPAGES==4
+       #define ARRAYSIZE 4950
+       #endif
+
+       #if MAXPAGES==9
+       #define ARRAYSIZE 10870
+       #endif
+
+       #if MAXPAGES==16
+       #define ARRAYSIZE 19240
+       #endif
+
+       #if MAXPAGES==25
+       #define ARRAYSIZE 30025
+       #endif
+
+       #if MAXPAGES==36
+       #define ARRAYSIZE 43217
+       #endif
+
+       #if MAXPAGES==49
+       #define ARRAYSIZE 58813
+       #endif
+
+       #if MAXPAGES==64
+       #define ARRAYSIZE 76810
+       #endif
+
+       #define IPPD 1200
+#endif
+
+#if HD_MODE==1
+       #if MAXPAGES==1
+       #define ARRAYSIZE 5092 
+       #endif
+
+       #if MAXPAGES==4
+       #define ARRAYSIZE 14844 
+       #endif
+
+       #if MAXPAGES==9
+       #define ARRAYSIZE 32600
+       #endif
+
+       #if MAXPAGES==16
+       #define ARRAYSIZE 57713
+       #endif
+
+       #if MAXPAGES==25
+       #define ARRAYSIZE 90072
+       #endif
+
+       #if MAXPAGES==36
+       #define ARRAYSIZE 129650
+       #endif
+
+       #if MAXPAGES==49 
+       #define ARRAYSIZE 176437
+       #endif
+
+       #if MAXPAGES==64
+       #define ARRAYSIZE 230430
+       #endif
+
+       #define IPPD 3600
 #endif
 
-#if MAXSLOTS==9
-#define ARRAYSIZE 10870
+#ifndef PI
+#define PI 3.141592653589793
 #endif
 
-#if MAXSLOTS==16
-#define ARRAYSIZE 19240
+#ifndef TWOPI
+#define TWOPI 6.283185307179586
 #endif
 
-#if MAXSLOTS==25
-#define ARRAYSIZE 30025
+#ifndef HALFPI
+#define HALFPI 1.570796326794896
 #endif
 
-char   string[255], sdf_path[255], opened=0, *splat_version={"1.2.0b"};
+#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 FOUR_THIRDS 1.3333333333333
+
+char   string[255], sdf_path[255], opened=0, gpsav=0, splat_name[10],
+       splat_version[6], dashes[80];
 
-double TWOPI=6.283185307179586, HALFPI=1.570796326794896,
-       PI=3.141592653589793, deg2rad=1.74532925199e-02,
-       EARTHRADIUS=20902230.97, METERS_PER_MILE=1609.344,
-       METERS_PER_FOOT=0.3048, KM_PER_MILE=1.609344, earthradius,
-       max_range=0.0;
+double earthradius, max_range=0.0, forced_erp=-1.0, dpp, ppd,
+       fzone_clearance=0.6, forced_freq, clutter;
 
-int    min_north=90, max_north=-90, min_west=360, max_west=-1,
-       max_elevation=-32768, min_elevation=32768, bzerror, maxdB=230;
+int    min_north=90, max_north=-90, min_west=360, max_west=-1, ippd, mpi,
+       max_elevation=-32768, min_elevation=32768, bzerror, contour_threshold;
 
-unsigned char got_elevation_pattern=0, got_azimuth_pattern=0, metric=0;
+unsigned char got_elevation_pattern, got_azimuth_pattern, metric=0, dbm=0;
 
 struct site {  double lat;
                double lon;
                float alt;
                char name[50];
+               char filename[255];
            }   site;
 
 struct path {  double lat[ARRAYSIZE];
@@ -88,9 +153,10 @@ struct dem {        int min_north;
                int max_west;
                int max_el;
                int min_el;
-               short data[1200][1200];
-               unsigned char mask[1200][1200];
-           }   dem[MAXSLOTS];
+               short data[IPPD][IPPD];
+               unsigned char mask[IPPD][IPPD];
+               unsigned char signal[IPPD][IPPD];
+           }   dem[MAXPAGES];
 
 struct LR {    double eps_dielect; 
                double sgm_conductivity; 
@@ -98,12 +164,18 @@ struct LR {        double eps_dielect;
                double frq_mhz; 
                double conf; 
                double rel;
+               double erp;
                int radio_climate;  
                int pol;
                float antenna_pattern[361][1001];
           }    LR;
 
-double elev_l[ARRAYSIZE+10];
+struct region { unsigned char color[32][3];
+               int level[32];
+               int levels;
+             } region;
+
+double elev[ARRAYSIZE+10];
 
 void point_to_point(double elev[], double tht_m, double rht_m,
          double eps_dielect, double sgm_conductivity, double eno_ns_surfref,
@@ -133,9 +205,30 @@ int ReduceAngle(double angle)
 
        double temp;
 
-       temp=acos(cos(angle*deg2rad));
+       temp=acos(cos(angle*DEG2RAD));
+
+       return (int)rint(temp/DEG2RAD);
+}
+
+double LonDiff(double lon1, double lon2)
+{
+       /* This function returns the short path longitudinal
+          difference between longitude1 and longitude2 
+          as an angle between -180.0 and +180.0 degrees.
+          If lon1 is west of lon2, the result is positive.
+          If lon1 is east of lon2, the result is negative. */
+
+       double diff;
+
+       diff=lon1-lon2;
+
+       if (diff<=-180.0)
+               diff+=360.0;
+
+       if (diff>=180.0)
+               diff-=360.0;
 
-       return (int)rint(temp/deg2rad);
+       return diff;
 }
 
 char *dec2dms(double decimal)
@@ -172,10 +265,42 @@ char *dec2dms(double decimal)
                seconds=59;
 
        string[0]=0;
-       sprintf(string,"%d%c %d\' %d\"", degrees*sign, 176, minutes, seconds);
+       snprintf(string,250,"%d%c %d\' %d\"", degrees*sign, 176, minutes, seconds);
        return (string);
 }
 
+int PutMask(double lat, double lon, int value)
+{
+       /* Lines, text, markings, and coverage areas are stored in a
+          mask that is combined with topology data when topographic
+          maps are generated by SPLAT!.  This function sets and resets
+          bits in the mask based on the latitude and longitude of the
+          area pointed to. */
+
+       int     x, y, indx;
+       char    found;
+
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+       {
+               x=(int)rint(ppd*(lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,lon)));
+
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
+                       found=1;
+               else
+                       indx++;
+       }
+
+       if (found)
+       {
+               dem[indx].mask[x][y]=value;
+               return ((int)dem[indx].mask[x][y]);
+       }
+
+       else
+               return -1;
+}
+
 int OrMask(double lat, double lon, int value)
 {
        /* Lines, text, markings, and coverage areas are stored in a
@@ -184,26 +309,24 @@ int OrMask(double lat, double lon, int value)
           the mask based on the latitude and longitude of the area
           pointed to. */
 
-       int     x, y, indx, minlat, minlon;
+       int     x, y, indx;
        char    found;
 
-       minlat=(int)floor(lat);
-       minlon=(int)floor(lon);
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+       {
+               x=(int)rint(ppd*(lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,lon)));
 
-       for (indx=0, found=0; indx<MAXSLOTS && found==0;)
-               if (minlat==dem[indx].min_north && minlon==dem[indx].min_west)
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
                        found=1;
                else
                        indx++;
+       }
 
        if (found)
        {
-               x=(int)(1199.0*(lat-floor(lat)));
-               y=(int)(1199.0*(lon-floor(lon)));
-
                dem[indx].mask[x][y]|=value;
-
-               return (dem[indx].mask[x][y]);
+               return ((int)dem[indx].mask[x][y]);
        }
 
        else
@@ -218,6 +341,61 @@ int GetMask(double lat, double lon)
        return (OrMask(lat,lon,0));
 }
 
+int PutSignal(double lat, double lon, unsigned char signal)
+{
+       /* This function writes a signal level (0-255)
+          at the specified location for later recall. */
+
+       int     x, y, indx;
+       char    found;
+
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+       {
+               x=(int)rint(ppd*(lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,lon)));
+
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
+                       found=1;
+               else
+                       indx++;
+       }
+
+       if (found)
+       {
+               dem[indx].signal[x][y]=signal;
+               return (dem[indx].signal[x][y]);
+       }
+
+       else
+               return 0;
+}
+
+unsigned char GetSignal(double lat, double lon)
+{
+       /* This function reads the signal level (0-255) at the
+          specified location that was previously written by the
+          complimentary PutSignal() function. */
+
+       int     x, y, indx;
+       char    found;
+
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+       {
+               x=(int)rint(ppd*(lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,lon)));
+
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
+                       found=1;
+               else
+                       indx++;
+       }
+
+       if (found)
+               return (dem[indx].signal[x][y]);
+       else
+               return 0;
+}
+
 double GetElevation(struct site location)
 {
        /* This function returns the elevation (in feet) of any location
@@ -225,26 +403,24 @@ double GetElevation(struct site location)
           Function returns -5000.0 for locations not found in memory. */
 
        char    found;
-       int     x, y, indx, minlat, minlon;
+       int     x, y, indx;
        double  elevation;
 
-       elevation=-5000.0;
-
-       minlat=(int)floor(location.lat);
-       minlon=(int)floor(location.lon);
-
-       x=(int)(1199.0*(location.lat-floor(location.lat)));
-       y=(int)(1199.0*(location.lon-floor(location.lon)));
-
-       for (indx=0, found=0; indx<MAXSLOTS && found==0; indx++)
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
        {
-               if (minlat==dem[indx].min_north && minlon==dem[indx].min_west)
-               {
+               x=(int)rint(ppd*(location.lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,location.lon)));
 
-                       elevation=3.28084*dem[indx].data[x][y];
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
                        found=1;
-               }
+               else
+                       indx++;
        }
+
+       if (found)
+               elevation=3.28084*dem[indx].data[x][y];
+       else
+               elevation=-5000.0;
        
        return elevation;
 }
@@ -257,24 +433,22 @@ int AddElevation(double lat, double lon, double height)
           not found in memory. */
 
        char    found;
-       int     x, y, indx, minlat, minlon;
+       int     x, y, indx;
 
-       minlat=(int)floor(lat);
-       minlon=(int)floor(lon);
-
-       x=(int)(1199.0*(lat-floor(lat)));
-       y=(int)(1199.0*(lon-floor(lon)));
-
-       for (indx=0, found=0; indx<MAXSLOTS && found==0; indx++)
+       for (indx=0, found=0; indx<MAXPAGES && found==0;)
        {
-               if (minlat==dem[indx].min_north && minlon==dem[indx].min_west)
-               {
+               x=(int)rint(ppd*(lat-dem[indx].min_north));
+               y=mpi-(int)rint(ppd*(LonDiff(dem[indx].max_west,lon)));
 
-                       dem[indx].data[x][y]+=(short)rint(height);
+               if (x>=0 && x<=mpi && y>=0 && y<=mpi)
                        found=1;
-               }
+               else
+                       indx++;
        }
-       
+
+       if (found)
+               dem[indx].data[x][y]+=(short)rint(height);
+
        return found;
 }
 
@@ -285,10 +459,10 @@ double Distance(struct site site1, struct site site2)
 
        double  lat1, lon1, lat2, lon2, distance;
 
-       lat1=site1.lat*deg2rad;
-       lon1=site1.lon*deg2rad;
-       lat2=site2.lat*deg2rad;
-       lon2=site2.lon*deg2rad;
+       lat1=site1.lat*DEG2RAD;
+       lon1=site1.lon*DEG2RAD;
+       lat2=site2.lat*DEG2RAD;
+       lon2=site2.lon*DEG2RAD;
 
        distance=3959.0*acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos((lon1)-(lon2)));
 
@@ -303,11 +477,11 @@ double Azimuth(struct site source, struct site destination)
        double  dest_lat, dest_lon, src_lat, src_lon,
                beta, azimuth, diff, num, den, fraction;
 
-       dest_lat=destination.lat*deg2rad;
-       dest_lon=destination.lon*deg2rad;
+       dest_lat=destination.lat*DEG2RAD;
+       dest_lon=destination.lon*DEG2RAD;
 
-       src_lat=source.lat*deg2rad;
-       src_lon=source.lon*deg2rad;
+       src_lat=source.lat*DEG2RAD;
+       src_lon=source.lon*DEG2RAD;
                
        /* Calculate Surface Distance */
 
@@ -344,7 +518,7 @@ double Azimuth(struct site source, struct site destination)
        if (diff>0.0)
                azimuth=TWOPI-azimuth;
 
-       return (azimuth/deg2rad);               
+       return (azimuth/DEG2RAD);               
 }
 
 double ElevationAngle(struct site source, struct site destination)
@@ -378,28 +552,55 @@ void ReadPath(struct site source, struct site destination)
 
        int     c;
        double  azimuth, distance, lat1, lon1, beta, den, num,
-               lat2, lon2, total_distance, x, y, path_length,
-               increment;
+               lat2, lon2, total_distance, dx, dy, path_length,
+               miles_per_sample, samples_per_radian=68755.0;
        struct  site tempsite;
 
-       lat1=source.lat*deg2rad;
-       lon1=source.lon*deg2rad;
+       lat1=source.lat*DEG2RAD;
+       lon1=source.lon*DEG2RAD;
+
+       lat2=destination.lat*DEG2RAD;
+       lon2=destination.lon*DEG2RAD;
+
+       if (ppd==1200.0)
+               samples_per_radian=68755.0;
 
-       lat2=destination.lat*deg2rad;
-       lon2=destination.lon*deg2rad;
+       if (ppd==3600.0)
+               samples_per_radian=206265.0;
 
-       azimuth=Azimuth(source,destination)*deg2rad;
+       azimuth=Azimuth(source,destination)*DEG2RAD;
 
        total_distance=Distance(source,destination);
 
-       x=68755.0*acos(cos(lon1-lon2));         /* 1200 samples per degree */
-       y=68755.0*acos(cos(lat1-lat2));         /* 68755 samples per radian */
+       if (total_distance>(30.0/ppd))          /* > 0.5 pixel distance */
+       {
+               dx=samples_per_radian*acos(cos(lon1-lon2));
+               dy=samples_per_radian*acos(cos(lat1-lat2));
+
+               path_length=sqrt((dx*dx)+(dy*dy));              /* Total number of samples */
+
+               miles_per_sample=total_distance/path_length;    /* Miles per sample */
+       }
 
-       path_length=sqrt((x*x)+(y*y));          /* Total number of samples */
+       else
+       {
+               c=0;
+               dx=0.0;
+               dy=0.0;
+               path_length=0.0;
+               miles_per_sample=0.0;
+               total_distance=0.0;
 
-       increment=total_distance/path_length;   /* Miles per sample */
+               lat1=lat1/DEG2RAD;
+               lon1=lon1/DEG2RAD;
+
+               path.lat[c]=lat1;
+               path.lon[c]=lon1;
+               path.elevation[c]=GetElevation(source);
+               path.distance[c]=0.0;
+       }
 
-       for (distance=0, c=0; distance<=total_distance; distance+=increment)
+       for (distance=0.0, c=0; (total_distance!=0.0 && distance<=total_distance && c<ARRAYSIZE); c++, distance=miles_per_sample*(double)c)
        {
                beta=distance/3959.0;
                lat2=asin(sin(lat1)*cos(beta)+cos(azimuth)*sin(beta)*cos(lat1));
@@ -410,10 +611,10 @@ void ReadPath(struct site source, struct site destination)
                        lon2=lon1+PI;
 
                else if (azimuth==HALFPI && (beta>HALFPI+lat1))
-                       lon2=lon1+PI;
+                               lon2=lon1+PI;
 
                else if (fabs(num/den)>1.0)
-                       lon2=lon1;
+                               lon2=lon1;
 
                else
                {
@@ -429,19 +630,15 @@ void ReadPath(struct site source, struct site destination)
                while (lon2>TWOPI)
                        lon2-=TWOPI;
  
-               lat2=lat2/deg2rad;
-               lon2=lon2/deg2rad;
+               lat2=lat2/DEG2RAD;
+               lon2=lon2/DEG2RAD;
 
-               if (c<ARRAYSIZE)
-               {
-                       path.lat[c]=lat2;
-                       path.lon[c]=lon2;
-                       tempsite.lat=lat2;
-                       tempsite.lon=lon2;
-                       path.elevation[c]=GetElevation(tempsite);
-                       path.distance[c]=distance;
-                       c++;
-               }
+               path.lat[c]=lat2;
+               path.lon[c]=lon2;
+               tempsite.lat=lat2;
+               tempsite.lon=lon2;
+               path.elevation[c]=GetElevation(tempsite);
+               path.distance[c]=distance;
        }
 
        /* Make sure exact destination point is recorded at path.length-1 */
@@ -500,7 +697,7 @@ double ElevationAngle2(struct site source, struct site destination, double er)
        {
                distance=5280.0*path.distance[x];
 
-               test_alt=earthradius+path.elevation[x];
+               test_alt=earthradius+(path.elevation[x]==0.0?path.elevation[x]:path.elevation[x]+clutter);
 
                cos_test_angle=((source_alt2)+(distance*distance)-(test_alt*test_alt))/(2.0*source_alt*distance);
 
@@ -512,10 +709,10 @@ double ElevationAngle2(struct site source, struct site destination, double er)
                   what it would be if the angles themselves
                   were compared. */
 
-               if (cos_xmtr_angle>cos_test_angle)
+               if (cos_xmtr_angle>=cos_test_angle)
                {
                        block=1;
-                       first_obstruction_angle=((acos(cos_test_angle))/deg2rad)-90.0;
+                       first_obstruction_angle=((acos(cos_test_angle))/DEG2RAD)-90.0;
                }
        }
 
@@ -523,7 +720,7 @@ double ElevationAngle2(struct site source, struct site destination, double er)
                elevation=first_obstruction_angle;
 
        else
-               elevation=((acos(cos_xmtr_angle))/deg2rad)-90.0;
+               elevation=((acos(cos_xmtr_angle))/DEG2RAD)-90.0;
 
        path=temp;
 
@@ -544,15 +741,15 @@ double AverageTerrain(struct site source, double azimuthx, double start_distance
        double  beta, lat1, lon1, lat2, lon2, num, den, azimuth, terrain=0.0;
        struct  site destination;
 
-       lat1=source.lat*deg2rad;
-       lon1=source.lon*deg2rad;
+       lat1=source.lat*DEG2RAD;
+       lon1=source.lon*DEG2RAD;
 
        /* Generate a path of elevations between the source
           location and the remote location provided. */
 
        beta=end_distance/3959.0;
 
-       azimuth=deg2rad*azimuthx;
+       azimuth=DEG2RAD*azimuthx;
 
        lat2=asin(sin(lat1)*cos(beta)+cos(azimuth)*sin(beta)*cos(lat1));
        num=cos(beta)-(sin(lat1)*sin(lat2));
@@ -562,10 +759,10 @@ double AverageTerrain(struct site source, double azimuthx, double start_distance
                lon2=lon1+PI;
 
        else if (azimuth==HALFPI && (beta>HALFPI+lat1))
-               lon2=lon1+PI;
+                       lon2=lon1+PI;
 
        else if (fabs(num/den)>1.0)
-               lon2=lon1;
+                       lon2=lon1;
 
        else
        {
@@ -581,8 +778,8 @@ double AverageTerrain(struct site source, double azimuthx, double start_distance
        while (lon2>TWOPI)
                lon2-=TWOPI;
  
-       lat2=lat2/deg2rad;
-       lon2=lon2/deg2rad;
+       lat2=lat2/DEG2RAD;
+       lon2=lon2/DEG2RAD;
 
        destination.lat=lat2;
        destination.lon=lon2;
@@ -610,7 +807,7 @@ double AverageTerrain(struct site source, double azimuthx, double start_distance
                {
                        if (path.distance[c]>=start_distance)
                        {
-                               terrain+=path.elevation[c];
+                               terrain+=(path.elevation[c]==0.0?path.elevation[c]:path.elevation[c]+clutter);
                                samples++;
                        }
                }
@@ -663,27 +860,6 @@ double haat(struct site antenna)
        }
 }
 
-float LonDiff(float lon1, float lon2)
-{
-       /* This function returns the short path longitudinal
-          difference between longitude1 and longitude2 
-          as an angle between -180.0 and +180.0 degrees.
-          If lon1 is west of lon2, the result is positive.
-          If lon1 is east of lon2, the result is negative. */
-
-       float diff;
-
-       diff=lon1-lon2;
-
-       if (diff<=-180.0)
-               diff+=360.0;
-
-       if (diff>=180.0)
-               diff-=360.0;
-
-       return diff;
-}
-
 void PlaceMarker(struct site location)
 {
        /* This function places text and marker data in the mask array
@@ -701,29 +877,30 @@ void PlaceMarker(struct site location)
        double  x, y, lat, lon, textx=0.0, texty=0.0, xmin, xmax,
                ymin, ymax, p1, p3, p6, p8, p12, p16, p24, label_length;
 
-       xmin=min_north;
-       xmax=max_north;
-       ymin=min_west;
-       ymax=max_west;
+       xmin=(double)min_north;
+       xmax=(double)max_north;
+       ymin=(double)min_west;
+       ymax=(double)max_west;
        lat=location.lat;
        lon=location.lon;
 
-       if (lat<xmax && lat>xmin && (LonDiff(lon,ymax)<0.0) && (LonDiff(lon,ymin)>0.0))
+       if (lat<xmax && lat>=xmin && (LonDiff(lon,ymax)<=0.0) && (LonDiff(lon,ymin)>=dpp))
        {
-               p1=1.0/1200.0;
-               p3=3.0/1200.0;
-               p6=6.0/1200.0;
-               p8=8.0/1200.0;
-               p12=12.0/1200.0;
-               p16=16.0/1200.0;
-               p24=24.0/1200.0;
+               p1=1.0/ppd;
+               p3=3.0/ppd;
+               p6=6.0/ppd;
+               p8=8.0/ppd;
+               p12=12.0/ppd;
+               p16=16.0/ppd;
+               p24=24.0/ppd;
+
                ok2print=0;
                occupied=0;
 
                /* Is Marker Position Clear Of Text Or Other Markers? */
 
-               for (x=lat-p3; (x<=xmax && x>=xmin && x<=lat+p3); x+=p1)
-                       for (y=lon-p3; (LonDiff(y,ymax)<=0.0) && (LonDiff(y,ymin)>=0.0) && (LonDiff(y,lon+p3)<=0.0); y+=p1)
+               for (a=0, x=lat-p3; (x<=xmax && x>=xmin && a<7); x+=p1, a++)
+                       for (b=0, y=lon-p3; (LonDiff(y,ymax)<=0.0) && (LonDiff(y,ymin)>=dpp) && b<7; y+=p1, b++)
                                occupied|=(GetMask(x,y)&2);
 
                if (occupied==0)
@@ -735,7 +912,7 @@ void PlaceMarker(struct site location)
 
                        label_length=p1*(double)(strlen(location.name)<<3);
 
-                       if ((LonDiff(lon+label_length,ymax)<=0.0) && (LonDiff(lon-label_length,ymin)>=0.0))
+                       if ((LonDiff(lon+label_length,ymax)<=0.0) && (LonDiff(lon-label_length,ymin)>=dpp))
                        {
                                /* Default: Centered Text */
 
@@ -800,7 +977,7 @@ void PlaceMarker(struct site location)
 
                        if (ok2print==0)
                        {
-                               if (LonDiff(lon-label_length,ymin)>=0.0)
+                               if (LonDiff(lon-label_length,ymin)>=dpp)
                                {
                                        /* Position Text To The
                                           Right Of The Marker */
@@ -871,8 +1048,8 @@ void PlaceMarker(struct site location)
 
                                x=textx;
                                y=texty;
-
-                               for (a=0; a<16 && ok2print; a++)
+                               
+                               for (a=0; a<16; a++)
                                {
                                        for (b=0; b<(int)strlen(location.name); b++)
                                        {
@@ -889,9 +1066,9 @@ void PlaceMarker(struct site location)
        
                                /* Draw Square Marker Centered
                                   On Location Specified */
-       
-                               for (x=lat-p3; (x<=xmax && x>=xmin && x<=lat+p3); x+=p1)
-                                       for (y=lon-p3; (LonDiff(y,ymax)<=0.0) && (LonDiff(y,ymin)>=0.0) && (LonDiff(y,lon+p3)<=0.0); y+=p1)
+
+                               for (a=0, x=lat-p3; (x<=xmax && x>=xmin && a<7); x+=p1, a++)
+                                       for (b=0, y=lon-p3; (LonDiff(y,ymax)<=0.0) && (LonDiff(y,ymin)>=dpp) && b<7; y+=p1, b++)
                                                OrMask(x,y,2);
                        }
                }
@@ -941,11 +1118,13 @@ double ReadBearing(char *input)
        if (b==0)  /* Decimal Format (40.139722) */
                sscanf(string,"%lf",&bearing);
 
-       if (b==2)  /* Degree, Minute, Second Format (40 08 23) */
+       if (b==2)  /* Degree, Minute, Second Format (40 08 23.xx) */
        {
                sscanf(string,"%d %d %lf",&degrees, &minutes, &seconds);
 
-               bearing=(double)abs(degrees)+((double)abs(minutes)/60)+(fabs(seconds)/3600);
+               bearing=fabs((double)degrees);
+               bearing+=fabs(((double)minutes)/60.0);
+               bearing+=fabs(seconds/3600.0);
 
                if ((degrees<0) || (minutes<0) || (seconds<0.0))
                        bearing=-bearing;
@@ -953,7 +1132,7 @@ double ReadBearing(char *input)
 
        /* Anything else returns a 0.0 */
 
-       if (bearing>360.0 || bearing<-90.0)
+       if (bearing>360.0 || bearing<-360.0)
                bearing=0.0;
 
        return bearing;
@@ -970,30 +1149,33 @@ struct site LoadQTH(char *filename)
           case meters is assumed, and is handled accordingly. */
 
        int     x;
-       char    string[50], qthfile[255];
+       char    string[50], qthfile[255], *s=NULL;
        struct  site tempsite;
        FILE    *fd=NULL;
 
-       for (x=0; filename[x]!='.' && filename[x]!=0 && x<250; x++)
-               qthfile[x]=filename[x];
+       x=strlen(filename);
+       strncpy(qthfile, filename, 254);
 
-       qthfile[x]='.';
-       qthfile[x+1]='q';
-       qthfile[x+2]='t';
-       qthfile[x+3]='h';
-       qthfile[x+4]=0;
+       if (qthfile[x-3]!='q' || qthfile[x-2]!='t' || qthfile[x-1]!='h')
+       {
+               if (x>249)
+                       qthfile[249]=0;
+
+               strncat(qthfile,".qth\0",5);
+       }
 
        tempsite.lat=91.0;
        tempsite.lon=361.0;
        tempsite.alt=0.0;
        tempsite.name[0]=0;
+       tempsite.filename[0]=0;
 
        fd=fopen(qthfile,"r");
 
        if (fd!=NULL)
        {
                /* Site Name */
-               fgets(string,49,fd);
+               s=fgets(string,49,fd);
 
                /* Strip <CR> and/or <LF> from end of site name */
 
@@ -1002,15 +1184,18 @@ struct site LoadQTH(char *filename)
                tempsite.name[x]=0;
 
                /* Site Latitude */
-               fgets(string,49,fd);
+               s=fgets(string,49,fd);
                tempsite.lat=ReadBearing(string);
 
                /* Site Longitude */
-               fgets(string,49,fd);
+               s=fgets(string,49,fd);
                tempsite.lon=ReadBearing(string);
 
+               if (tempsite.lon<0.0)
+                       tempsite.lon+=360.0;
+
                /* Antenna Height */
-               fgets(string,49,fd);
+               s=fgets(string,49,fd);
                fclose(fd);
 
                /* Remove <CR> and/or <LF> from antenna height string */
@@ -1025,6 +1210,7 @@ struct site LoadQTH(char *filename)
                   must be converted to feet before exiting. */
 
                for (x=0; string[x]!='M' && string[x]!='m' && string[x]!=0 && x<48; x++);
+
                if (string[x]=='M' || string[x]=='m')
                {
                        string[x]=0;
@@ -1037,6 +1223,11 @@ struct site LoadQTH(char *filename)
                        string[x]=0;
                        sscanf(string,"%f",&tempsite.alt);
                }
+
+               for (x=0; x<254 && qthfile[x]!=0; x++)
+                       tempsite.filename[x]=qthfile[x];
+
+               tempsite.filename[x]=0;
        }
 
        return tempsite;
@@ -1049,11 +1240,11 @@ void LoadPAT(char *filename)
           loaded SPLAT! .lrp files.  */
 
        int     a, b, w, x, y, z, last_index, next_index, span;
-       char    string[255], azfile[255], elfile[255], *pointer=NULL;
+       char    string[255], azfile[255], elfile[255], *pointer=NULL, *s=NULL;
        float   az, xx, elevation, amplitude, rotation, valid1, valid2,
                delta, azimuth[361], azimuth_pattern[361], el_pattern[10001],
                elevation_pattern[361][1001], slant_angle[361], tilt,
-               mechanical_tilt, tilt_azimuth, tilt_increment, sum;
+               mechanical_tilt=0.0, tilt_azimuth, tilt_increment, sum;
        FILE    *fd=NULL;
        unsigned char read_count[10001];
 
@@ -1075,6 +1266,9 @@ void LoadPAT(char *filename)
 
        rotation=0.0;
 
+       got_azimuth_pattern=0;
+       got_elevation_pattern=0;
+
        /* Load .az antenna pattern file */
 
        fd=fopen(azfile,"r");
@@ -1094,7 +1288,7 @@ void LoadPAT(char *filename)
                   in degrees measured clockwise
                   from true North. */
 
-               fgets(string,254,fd);
+               s=fgets(string,254,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -1107,7 +1301,7 @@ void LoadPAT(char *filename)
                   normalized field radiation pattern amplitude
                   (0.0 to 1.0) until EOF is reached. */
 
-               fgets(string,254,fd);
+               s=fgets(string,254,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -1125,7 +1319,7 @@ void LoadPAT(char *filename)
                                read_count[x]++;
                        }
 
-                       fgets(string,254,fd);
+                       s=fgets(string,254,fd);
                        pointer=strchr(string,';');
 
                        if (pointer!=NULL)
@@ -1228,7 +1422,7 @@ void LoadPAT(char *filename)
                   tilt azimuth in degrees measured
                   clockwise from true North. */  
 
-               fgets(string,254,fd);
+               s=fgets(string,254,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -1240,7 +1434,7 @@ void LoadPAT(char *filename)
                   normalized field radiation pattern amplitude
                   (0.0 to 1.0) until EOF is reached. */
 
-               fgets(string,254,fd);
+               s=fgets(string,254,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -1262,7 +1456,7 @@ void LoadPAT(char *filename)
                                read_count[x]++;
                        }
 
-                       fgets(string,254,fd);
+                       s=fgets(string,254,fd);
                        pointer=strchr(string,';');
 
                        if (pointer!=NULL)
@@ -1414,8 +1608,8 @@ int LoadSDF_SDF(char *name)
           dem[] structure. */
 
        int     x, y, data, indx, minlat, minlon, maxlat, maxlon;
-       char    found, free_slot=0, line[20], sdf_file[255],
-               path_plus_name[255];
+       char    found, free_page=0, line[20], sdf_file[255],
+               path_plus_name[255], *s=NULL;
        FILE    *fd;
 
        for (x=0; name[x]!='.' && name[x]!=0 && x<250; x++)
@@ -1435,7 +1629,7 @@ int LoadSDF_SDF(char *name)
 
        /* Is it already in memory? */
 
-       for (indx=0, found=0; indx<MAXSLOTS && found==0; indx++)
+       for (indx=0, found=0; indx<MAXPAGES && found==0; indx++)
        {
                if (minlat==dem[indx].min_north && minlon==dem[indx].min_west && maxlat==dem[indx].max_north && maxlon==dem[indx].max_west)
                        found=1;
@@ -1445,14 +1639,14 @@ int LoadSDF_SDF(char *name)
 
        if (found==0)
        {       
-               for (indx=0, free_slot=0; indx<MAXSLOTS && free_slot==0; indx++)
+               for (indx=0, free_page=0; indx<MAXPAGES && free_page==0; indx++)
                        if (dem[indx].max_north==-90)
-                               free_slot=1;
+                               free_page=1;
        }
 
        indx--;
 
-       if (free_slot && found==0 && indx>=0 && indx<MAXSLOTS)
+       if (free_page && found==0 && indx>=0 && indx<MAXPAGES)
        {
                /* Search for SDF file in current working directory first */
 
@@ -1473,28 +1667,30 @@ int LoadSDF_SDF(char *name)
 
                if (fd!=NULL)
                {
-                       fprintf(stdout,"Loading \"%s\" into slot %d...",path_plus_name,indx+1);
+                       fprintf(stdout,"Loading \"%s\" into page %d...",path_plus_name,indx+1);
                        fflush(stdout);
 
-                       fgets(line,19,fd);
+                       s=fgets(line,19,fd);
                        sscanf(line,"%d",&dem[indx].max_west);
 
-                       fgets(line,19,fd);
+                       s=fgets(line,19,fd);
                        sscanf(line,"%d",&dem[indx].min_north);
 
-                       fgets(line,19,fd);
+                       s=fgets(line,19,fd);
                        sscanf(line,"%d",&dem[indx].min_west);
 
-                       fgets(line,19,fd);
+                       s=fgets(line,19,fd);
                        sscanf(line,"%d",&dem[indx].max_north);
 
-                       for (x=0; x<1200; x++)
-                               for (y=0; y<1200; y++)
+                       for (x=0; x<ippd; x++)
+                               for (y=0; y<ippd; y++)
                                {
-                                       fgets(line,19,fd);
-                                       sscanf(line,"%d",&data);
+                                       s=fgets(line,19,fd);
+                                       data=atoi(line);
 
                                        dem[indx].data[x][y]=data;
+                                       dem[indx].signal[x][y]=0;
+                                       dem[indx].mask[x][y]=0;
 
                                        if (data>dem[indx].max_el)
                                                dem[indx].max_el=data;
@@ -1515,13 +1711,13 @@ int LoadSDF_SDF(char *name)
                                max_north=dem[indx].max_north;
 
                        else if (dem[indx].max_north>max_north)
-                               max_north=dem[indx].max_north;
+                                       max_north=dem[indx].max_north;
 
                        if (min_north==90)
                                min_north=dem[indx].min_north;
 
                        else if (dem[indx].min_north<min_north)
-                               min_north=dem[indx].min_north;
+                                       min_north=dem[indx].min_north;
 
                        if (max_west==-1)
                                max_west=dem[indx].max_west;
@@ -1546,7 +1742,7 @@ int LoadSDF_SDF(char *name)
 
                        else
                        {
-                               if (abs(dem[indx].min_west-min_west)<180)
+                               if (fabs(dem[indx].min_west-min_west)<180.0)
                                {
                                        if (dem[indx].min_west<min_west)
                                                min_west=dem[indx].min_west;
@@ -1561,6 +1757,7 @@ int LoadSDF_SDF(char *name)
 
                        fprintf(stdout," Done!\n");
                        fflush(stdout);
+
                        return 1;
                }
 
@@ -1639,7 +1836,7 @@ int LoadSDF_BZ(char *name)
           stored in the first available dem[] structure. */
 
        int     x, y, data, indx, minlat, minlon, maxlat, maxlon;
-       char    found, free_slot=0, sdf_file[255], path_plus_name[255];
+       char    found, free_page=0, sdf_file[255], path_plus_name[255], *string;
        FILE    *fd;
        BZFILE  *bzfd;
 
@@ -1664,7 +1861,7 @@ int LoadSDF_BZ(char *name)
 
        /* Is it already in memory? */
 
-       for (indx=0, found=0; indx<MAXSLOTS && found==0; indx++)
+       for (indx=0, found=0; indx<MAXPAGES && found==0; indx++)
        {
                if (minlat==dem[indx].min_north && minlon==dem[indx].min_west && maxlat==dem[indx].max_north && maxlon==dem[indx].max_west)
                        found=1;
@@ -1674,14 +1871,14 @@ int LoadSDF_BZ(char *name)
 
        if (found==0)
        {       
-               for (indx=0, free_slot=0; indx<MAXSLOTS && free_slot==0; indx++)
+               for (indx=0, free_page=0; indx<MAXPAGES && free_page==0; indx++)
                        if (dem[indx].max_north==-90)
-                               free_slot=1;
+                               free_page=1;
        }
 
        indx--;
 
-       if (free_slot && found==0 && indx>=0 && indx<MAXSLOTS)
+       if (free_page && found==0 && indx>=0 && indx<MAXPAGES)
        {
                /* Search for SDF file in current working directory first */
 
@@ -1704,7 +1901,7 @@ int LoadSDF_BZ(char *name)
 
                if (fd!=NULL && bzerror==BZ_OK)
                {
-                       fprintf(stdout,"Loading \"%s\" into slot %d...",path_plus_name,indx+1);
+                       fprintf(stdout,"Loading \"%s\" into page %d...",path_plus_name,indx+1);
                        fflush(stdout);
 
                        sscanf(BZfgets(bzfd,255),"%d",&dem[indx].max_west);
@@ -1712,12 +1909,15 @@ int LoadSDF_BZ(char *name)
                        sscanf(BZfgets(bzfd,255),"%d",&dem[indx].min_west);
                        sscanf(BZfgets(bzfd,255),"%d",&dem[indx].max_north);
        
-                       for (x=0; x<1200; x++)
-                               for (y=0; y<1200; y++)
+                       for (x=0; x<ippd; x++)
+                               for (y=0; y<ippd; y++)
                                {
-                                       sscanf(BZfgets(bzfd,20),"%d",&data);
+                                       string=BZfgets(bzfd,20);
+                                       data=atoi(string);
 
                                        dem[indx].data[x][y]=data;
+                                       dem[indx].signal[x][y]=0;
+                                       dem[indx].mask[x][y]=0;
 
                                        if (data>dem[indx].max_el)
                                                dem[indx].max_el=data;
@@ -1740,13 +1940,13 @@ int LoadSDF_BZ(char *name)
                                max_north=dem[indx].max_north;
 
                        else if (dem[indx].max_north>max_north)
-                               max_north=dem[indx].max_north;
+                                       max_north=dem[indx].max_north;
 
                        if (min_north==90)
                                min_north=dem[indx].min_north;
 
                        else if (dem[indx].min_north<min_north)
-                               min_north=dem[indx].min_north;
+                                       min_north=dem[indx].min_north;
 
                        if (max_west==-1)
                                max_west=dem[indx].max_west;
@@ -1786,6 +1986,7 @@ int LoadSDF_BZ(char *name)
 
                        fprintf(stdout," Done!\n");
                        fflush(stdout);
+
                        return 1;
                }
 
@@ -1809,7 +2010,7 @@ char LoadSDF(char *name)
           requested must be entirely over water. */
 
        int     x, y, indx, minlat, minlon, maxlat, maxlon;
-       char    found, free_slot=0;
+       char    found, free_page=0;
        int     return_value=-1;
 
        /* Try to load an uncompressed SDF first. */
@@ -1831,7 +2032,7 @@ char LoadSDF(char *name)
 
                /* Is it already in memory? */
 
-               for (indx=0, found=0; indx<MAXSLOTS && found==0; indx++)
+               for (indx=0, found=0; indx<MAXPAGES && found==0; indx++)
                {
                        if (minlat==dem[indx].min_north && minlon==dem[indx].min_west && maxlat==dem[indx].max_north && maxlon==dem[indx].max_west)
                                found=1;
@@ -1841,16 +2042,16 @@ char LoadSDF(char *name)
 
                if (found==0)
                {       
-                       for (indx=0, free_slot=0; indx<MAXSLOTS && free_slot==0; indx++)
+                       for (indx=0, free_page=0; indx<MAXPAGES && free_page==0; indx++)
                                if (dem[indx].max_north==-90)
-                                       free_slot=1;
+                                       free_page=1;
                }
 
                indx--;
 
-               if (free_slot && found==0 && indx>=0 && indx<MAXSLOTS)
+               if (free_page && found==0 && indx>=0 && indx<MAXPAGES)
                {
-                       fprintf(stdout,"Region  \"%s\" assumed as sea-level into slot %d...",name,indx+1);
+                       fprintf(stdout,"Region  \"%s\" assumed as sea-level into page %d...",name,indx+1);
                        fflush(stdout);
 
                        dem[indx].max_west=maxlon;
@@ -1860,10 +2061,12 @@ char LoadSDF(char *name)
 
                        /* Fill DEM with sea-level topography */
 
-                       for (x=0; x<1200; x++)
-                               for (y=0; y<1200; y++)
+                       for (x=0; x<ippd; x++)
+                               for (y=0; y<ippd; y++)
                                {
                                        dem[indx].data[x][y]=0;
+                                       dem[indx].signal[x][y]=0;
+                                       dem[indx].mask[x][y]=0;
 
                                        if (dem[indx].min_el>0)
                                                dem[indx].min_el=0;
@@ -1879,13 +2082,13 @@ char LoadSDF(char *name)
                                max_north=dem[indx].max_north;
 
                        else if (dem[indx].max_north>max_north)
-                               max_north=dem[indx].max_north;
+                                       max_north=dem[indx].max_north;
 
                        if (min_north==90)
                                min_north=dem[indx].min_north;
 
                        else if (dem[indx].min_north<min_north)
-                               min_north=dem[indx].min_north;
+                                       min_north=dem[indx].min_north;
 
                        if (max_west==-1)
                                max_west=dem[indx].max_west;
@@ -1940,7 +2143,7 @@ void LoadCities(char *filename)
           read on topographic maps generated by SPLAT! */
 
        int     x, y, z;
-       char    input[80], str[3][80];
+       char    input[80], str[3][80], *s=NULL;
        struct  site city_site;
        FILE    *fd=NULL;
 
@@ -1948,9 +2151,9 @@ void LoadCities(char *filename)
 
        if (fd!=NULL)
        {
-               fgets(input,78,fd);
+               s=fgets(input,78,fd);
 
-               fprintf(stdout,"Reading \"%s\"... ",filename);
+               fprintf(stdout,"\nReading \"%s\"... ",filename);
                fflush(stdout);
 
                while (fd!=NULL && feof(fd)==0)
@@ -1978,18 +2181,21 @@ void LoadCities(char *filename)
                        city_site.lon=ReadBearing(str[2]);
                        city_site.alt=0.0;
 
+                       if (city_site.lon<0.0)
+                               city_site.lon+=360.0;
+
                        PlaceMarker(city_site);
 
-                       fgets(input,78,fd);
+                       s=fgets(input,78,fd);
                }
 
                fclose(fd);
-               fprintf(stdout,"Done!\n");
+               fprintf(stdout,"Done!");
                fflush(stdout);
        }
 
        else
-               fprintf(stderr,"*** ERROR: \"%s\": not found!\n",filename);
+               fprintf(stderr,"\n*** ERROR: \"%s\": not found!",filename);
 }
 
 void LoadUDT(char *filename)
@@ -2002,14 +2208,12 @@ void LoadUDT(char *filename)
           are added to the ground elevations described by the digital
           elevation data already loaded into memory. */
 
-       int     i, x, y, z, fd=0;
-       char    input[80], str[3][80], tempname[15], *pointer=NULL;
-       double  latitude, longitude, height, templat, templon,
-               tempheight, one_pixel;
+       int     i, x, y, z, ypix, xpix, tempxpix, tempypix, fd=0, n=0;
+       char    input[80], str[3][80], tempname[15], *pointer=NULL, *s=NULL;
+       double  latitude, longitude, height, tempheight;
        FILE    *fd1=NULL, *fd2=NULL;
 
        strcpy(tempname,"/tmp/XXXXXX\0");
-       one_pixel=1.0/1200.0;
 
        fd1=fopen(filename,"r");
 
@@ -2018,14 +2222,14 @@ void LoadUDT(char *filename)
                fd=mkstemp(tempname);
                fd2=fopen(tempname,"w");
 
-               fgets(input,78,fd1);
+               s=fgets(input,78,fd1);
 
                pointer=strchr(input,';');
 
                if (pointer!=NULL)
                        *pointer=0;
 
-               fprintf(stdout,"Reading \"%s\"... ",filename);
+               fprintf(stdout,"\nReading \"%s\"... ",filename);
                fflush(stdout);
 
                while (feof(fd1)==0)
@@ -2051,6 +2255,9 @@ void LoadUDT(char *filename)
                        latitude=ReadBearing(str[0]);
                        longitude=ReadBearing(str[1]);
 
+                       if (longitude<0.0)
+                               longitude+=360.0;
+
                        /* Remove <CR> and/or <LF> from antenna height string */
 
                        for (i=0; str[2][i]!=13 && str[2][i]!=10 && str[2][i]!=0; i++);
@@ -2075,13 +2282,13 @@ void LoadUDT(char *filename)
                        else
                        {
                                str[2][i]=0;
-                               height=rint(3.28084*atof(str[2]));
+                               height=rint(METERS_PER_FOOT*atof(str[2]));
                        }
 
                        if (height>0.0)
-                               fprintf(fd2,"%f, %f, %f\n",latitude, longitude, height);
+                               fprintf(fd2,"%d, %d, %f\n",(int)rint(latitude/dpp), (int)rint(longitude/dpp), height);
 
-                       fgets(input,78,fd1);
+                       s=fgets(input,78,fd1);
 
                        pointer=strchr(input,';');
 
@@ -2093,34 +2300,50 @@ void LoadUDT(char *filename)
                fclose(fd2);
                close(fd);
 
-               fprintf(stdout,"Done!\n");
+               fprintf(stdout,"Done!");
                fflush(stdout);
 
                fd1=fopen(tempname,"r");
                fd2=fopen(tempname,"r");
 
-               fscanf(fd1,"%lf, %lf, %lf", &latitude, &longitude, &height);
+               y=0;
+
+               n=fscanf(fd1,"%d, %d, %lf", &xpix, &ypix, &height);
 
-               for (y=0; feof(fd1)==0; y++)
+               do
                {
-                       rewind(fd2);
+                       x=0;
+                       z=0;
 
-                       fscanf(fd2,"%lf, %lf, %lf", &templat, &templon, &tempheight);
+                       n=fscanf(fd2,"%d, %d, %lf", &tempxpix, &tempypix, &tempheight);
 
-                       for (x=0, z=0; feof(fd2)==0; x++)
+                       do
                        {
-                               if (x>y)
-                                       if (fabs(latitude-templat)<=one_pixel && fabs(longitude-templon)<=one_pixel)
-                                               z=1;
+                               if (x>y && xpix==tempxpix && ypix==tempypix)
+                               {
+                                               z=1;  /* Dupe! */
 
-                               fscanf(fd2,"%lf, %lf, %lf", &templat, &templon, &tempheight);
-                       }
+                                               if (tempheight>height)
+                                                       height=tempheight;
+                               }
+
+                               else
+                               {
+                                       n=fscanf(fd2,"%d, %d, %lf", &tempxpix, &tempypix, &tempheight);
+                                       x++;
+                               }
 
-                       if (z==0)
-                               AddElevation(latitude, longitude, height);
+                       } while (feof(fd2)==0 && z==0);
 
-                       fscanf(fd1,"%lf, %lf, %lf", &latitude, &longitude, &height);
-               }
+                       if (z==0)  /* No duplicate found */
+                               AddElevation(xpix*dpp, ypix*dpp, height);
+
+                       n=fscanf(fd1,"%d, %d, %lf", &xpix, &ypix, &height);
+                       y++;
+
+                       rewind(fd2);
+
+               } while (feof(fd1)==0);
 
                fclose(fd1);
                fclose(fd2);
@@ -2128,7 +2351,9 @@ void LoadUDT(char *filename)
        }
 
        else
-               fprintf(stderr,"*** ERROR: \"%s\": not found!\n",filename);
+               fprintf(stderr,"\n*** ERROR: \"%s\": not found!",filename);
+
+       fprintf(stdout,"\n");
 }
 
 void LoadBoundaries(char *filename)
@@ -2141,7 +2366,7 @@ void LoadBoundaries(char *filename)
 
        int     x;
        double  lat0, lon0, lat1, lon1;
-       char    string[80];
+       char    string[80], *s=NULL;
        struct  site source, destination;
        FILE    *fd=NULL;
 
@@ -2149,28 +2374,25 @@ void LoadBoundaries(char *filename)
 
        if (fd!=NULL)
        {
-               fgets(string,78,fd);
+               s=fgets(string,78,fd);
 
-               fprintf(stdout,"Reading \"%s\"... ",filename);
+               fprintf(stdout,"\nReading \"%s\"... ",filename);
                fflush(stdout);
 
                do
                {
-                       fgets(string,78,fd);
+                       s=fgets(string,78,fd);
                        sscanf(string,"%lf %lf", &lon0, &lat0);
-                       fgets(string,78,fd);
+                       s=fgets(string,78,fd);
 
                        do
                        {
                                sscanf(string,"%lf %lf", &lon1, &lat1);
 
-                               lon0=fabs(lon0);
-                               lon1=fabs(lon1);
-
                                source.lat=lat0;
-                               source.lon=lon0;
+                               source.lon=(lon0>0.0 ? 360.0-lon0 : -lon0);
                                destination.lat=lat1;
-                               destination.lon=lon1;
+                               destination.lon=(lon1>0.0 ? 360.0-lon1 : -lon1);
 
                                ReadPath(source,destination);
 
@@ -2180,55 +2402,56 @@ void LoadBoundaries(char *filename)
                                lat0=lat1;
                                lon0=lon1;
 
-                               fgets(string,78,fd);
+                               s=fgets(string,78,fd);
 
                        } while (strncmp(string,"END",3)!=0 && feof(fd)==0);
 
-                       fgets(string,78,fd);
+                       s=fgets(string,78,fd);
 
                } while (strncmp(string,"END",3)!=0 && feof(fd)==0);
 
                fclose(fd);
 
-               fprintf(stdout,"Done!\n");
+               fprintf(stdout,"Done!");
                fflush(stdout);
        }
 
        else
-               fprintf(stderr,"*** ERROR: \"%s\": not found!\n",filename);
+               fprintf(stderr,"\n*** ERROR: \"%s\": not found!",filename);
 }
 
-void ReadLRParm(char *txsite_filename)
+char ReadLRParm(struct site txsite, char forced_read)
 {
        /* This function reads Longley-Rice parameter data for the
           transmitter site.  The file name is the same as the txsite,
           except the filename extension is .lrp.  If the needed file
           is not found, then the file "splat.lrp" is read from the
-          current working directory.  Failure to load this file will
-          result in the default parameters hard coded into this
-          function to be used and written to "splat.lrp". */
+          current working directory.  Failure to load this file under
+          a forced_read condition will result in the default parameters
+          hard coded into this function to be used and written to
+          "splat.lrp". */
 
        double  din;
-       char    filename[255], string[80], *pointer=NULL;
+       char    filename[255], string[80], *pointer=NULL, *s=NULL, return_value=0;
        int     iin, ok=0, x;
        FILE    *fd=NULL, *outfile=NULL;
 
-       /* Default parameters in case things go bad */
+       /* Default parameters */
 
-       LR.eps_dielect=15.0;
-       LR.sgm_conductivity=0.005;
-       LR.eno_ns_surfref=301.0;
-       LR.frq_mhz=300.0;
-       LR.radio_climate=5;
+       LR.eps_dielect=0.0;
+       LR.sgm_conductivity=0.0;
+       LR.eno_ns_surfref=0.0;
+       LR.frq_mhz=0.0;
+       LR.radio_climate=0;
        LR.pol=0;
-       LR.conf=0.50;
-       LR.rel=0.50;
+       LR.conf=0.0;
+       LR.rel=0.0;
+       LR.erp=0.0;
 
-       /* Modify txsite filename to one with a .lrp extension. */
+       /* Generate .lrp filename from txsite filename. */
 
-       strncpy(filename,txsite_filename,255);
-
-       for (x=0; filename[x]!='.' && filename[x]!=0 && filename[x]!='\n' && x<249; x++);
+       for (x=0; txsite.filename[x]!='.' && txsite.filename[x]!=0 && x<250; x++)
+               filename[x]=txsite.filename[x];
 
        filename[x]='.';
        filename[x+1]='l';
@@ -2248,7 +2471,7 @@ void ReadLRParm(char *txsite_filename)
 
        if (fd!=NULL)
        {
-               fgets(string,80,fd);
+               s=fgets(string,80,fd);
 
                pointer=strchr(string,';');
 
@@ -2261,7 +2484,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.eps_dielect=din;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2275,7 +2498,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.sgm_conductivity=din;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2289,7 +2512,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.eno_ns_surfref=din;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2303,7 +2526,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.frq_mhz=din;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2317,7 +2540,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.radio_climate=iin;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2331,7 +2554,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.pol=iin;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2345,7 +2568,7 @@ void ReadLRParm(char *txsite_filename)
                {
                        LR.conf=din;
 
-                       fgets(string,80,fd);
+                       s=fgets(string,80,fd);
 
                        pointer=strchr(string,';');
 
@@ -2355,19 +2578,61 @@ void ReadLRParm(char *txsite_filename)
                        ok=sscanf(string,"%lf", &din);
                }
 
-               fclose(fd);
-
                if (ok)
                {
                        LR.rel=din;
-                       LoadPAT(filename);
+                       din=0.0;
+                       return_value=1;
+
+                       if (fgets(string,80,fd)!=NULL)
+                       {
+                               pointer=strchr(string,':');
+
+                               if (pointer!=NULL)
+                                       *pointer=0;
+
+                               if (sscanf(string,"%lf", &din))
+                                       LR.erp=din;
+
+                               /* ERP in SPLAT! is referenced to 1 Watt
+                                  into a dipole (0 dBd).  If ERP is
+                                  expressed in dBm (referenced to a
+                                  0 dBi radiator), convert dBm in EIRP
+                                  to ERP.  */
+
+                               if ((strstr(string, "dBm")!=NULL) || (strstr(string,"dbm")!=NULL))
+                                       LR.erp=(pow(10.0,(LR.erp-32.14)/10.0));
+                       }
                }
+
+               fclose(fd);
+
+               if (forced_erp!=-1.0)
+                       LR.erp=forced_erp;
+
+               if (forced_freq>=20.0 && forced_freq<=20000.0)
+                       LR.frq_mhz=forced_freq;
+
+               if (ok)
+                       LoadPAT(filename);
        } 
 
-       if (fd==NULL)
+       if (fd==NULL && forced_read)
        {
-               /* Create a "splat.lrp" file since one
-                  could not be successfully loaded. */
+               /* Assign some default parameters
+                  for use in this run. */
+
+               LR.eps_dielect=15.0;
+               LR.sgm_conductivity=0.005;
+               LR.eno_ns_surfref=301.0;
+               LR.frq_mhz=300.0;
+               LR.radio_climate=5;
+               LR.pol=0;
+               LR.conf=0.50;
+               LR.rel=0.50;
+               LR.erp=0.0;
+
+               /* Write them to a "splat.lrp" file. */
 
                outfile=fopen("splat.lrp","w");
 
@@ -2378,16 +2643,38 @@ void ReadLRParm(char *txsite_filename)
                fprintf(outfile,"%d\t; Radio Climate\n",LR.radio_climate);
                fprintf(outfile,"%d\t; Polarization (0 = Horizontal, 1 = Vertical)\n", LR.pol);
                fprintf(outfile,"%.2f\t; Fraction of situations\n",LR.conf);
-               fprintf(outfile, "%.2f\t; Fraction of time\n",LR.rel);
+               fprintf(outfile,"%.2f\t; Fraction of time\n",LR.rel);
+               fprintf(outfile,"%.2f\t; Transmitter Effective Radiated Power in Watts or dBm (optional)\n",LR.erp);
                fprintf(outfile,"\nPlease consult SPLAT! documentation for the meaning and use of this data.\n");
 
                fclose(outfile);
 
-               fprintf(stderr,"\n%c*** There were problems reading your \"%s\" file! ***\nA \"splat.lrp\" file was written to your directory with default data.\n",7,filename);
+               return_value=1;
+
+               fprintf(stderr,"\n\n%c*** There were problems reading your \"%s\" file! ***\nA \"splat.lrp\" file was written to your directory with default data.\n",7,filename);
        }
 
-       if (fd==NULL || ok==0)
+       else if (forced_read==0)
+                       return_value=0;
+
+       if (forced_read && (fd==NULL || ok==0))
+       {
+               LR.eps_dielect=15.0;
+               LR.sgm_conductivity=0.005;
+               LR.eno_ns_surfref=301.0;
+               LR.frq_mhz=300.0;
+               LR.radio_climate=5;
+               LR.pol=0;
+               LR.conf=0.50;
+               LR.rel=0.50;
+               LR.erp=0.0;
+
                fprintf(stderr,"Longley-Rice default parameters have been assumed for this analysis.\n");
+
+               return_value=1;
+       }
+
+       return (return_value);
 }
 
 void PlotPath(struct site source, struct site destination, char mask_value)
@@ -2427,7 +2714,7 @@ void PlotPath(struct site source, struct site destination, char mask_value)
                        for (x=y, block=0; x>=0 && block==0; x--)
                        {
                                distance=5280.0*(path.distance[y]-path.distance[x]);
-                               test_alt=earthradius+path.elevation[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);
 
@@ -2438,7 +2725,7 @@ void PlotPath(struct site source, struct site destination, char mask_value)
                                   statement is reversed from what it would
                                   be if the actual angles were compared. */
 
-                               if (cos_xmtr_angle>cos_test_angle)
+                               if (cos_xmtr_angle>=cos_test_angle)
                                        block=1;
                        }
 
@@ -2448,28 +2735,34 @@ void PlotPath(struct site source, struct site destination, char mask_value)
        }
 }
 
-void PlotLRPath(struct site source, struct site destination, FILE *fd)
+void PlotLRPath(struct site source, struct site destination, unsigned char mask_value, FILE *fd)
 {
        /* This function plots the RF path loss between source and
           destination points based on the Longley-Rice propagation
           model, taking into account antenna pattern data, if available. */
 
+       int     x, y, ifs, ofs, errnum;
        char    block=0, strmode[100];
-       int     x, y, errnum;
        double  loss, azimuth, pattern=0.0, 
-               source_alt, dest_alt, source_alt2, dest_alt2,
-               cos_xmtr_angle, cos_test_angle=0.0, test_alt,
-               elevation, distance=0.0, four_thirds_earth;
+               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;
        struct  site temp;
 
        ReadPath(source,destination);
 
-       four_thirds_earth=EARTHRADIUS*(4.0/3.0);
+       four_thirds_earth=FOUR_THIRDS*EARTHRADIUS;
 
-       /* Copy elevations along path into the elev_l[] array. */
+       /* Copy elevations plus clutter along path into the elev[] array. */
 
-       for (x=0; x<path.length; x++)
-               elev_l[x+2]=path.elevation[x]*METERS_PER_FOOT;
+       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
@@ -2479,60 +2772,72 @@ void PlotLRPath(struct site source, struct site destination, FILE *fd)
           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.  (Using path.length-1
-          below avoids a Longley-Rice model error from occuring at
-          the destination point.) */
+          calculation for overall path loss. */
 
        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])==0)
+               if ((GetMask(path.lat[y],path.lon[y])&248)!=(mask_value<<3))
                {
                        distance=5280.0*path.distance[y];
-                       source_alt=four_thirds_earth+source.alt+path.elevation[0];
+                       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;
-                       source_alt2=source_alt*source_alt;
+                       xmtr_alt2=xmtr_alt*xmtr_alt;
 
                        /* Calculate the cosine of the elevation of
                           the receiver as seen by the transmitter. */
 
-                       cos_xmtr_angle=((source_alt2)+(distance*distance)-(dest_alt2))/(2.0*source_alt*distance);
+                       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)
                        {
-                               /* If no antenna elevation pattern is available, and
-                                  no output file is designated, the following code
-                                  that determines the elevation angle to the first
-                                  obstruction along the path is bypassed. */
+                               /* 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=5280.0*path.distance[x];
-                                       test_alt=four_thirds_earth+path.elevation[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=((source_alt2)+(distance*distance)-(test_alt*test_alt))/(2.0*source_alt*distance);
+                                       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
+                                          what it would be if the angles themselves
                                           were compared. */
 
-                                       if (cos_xmtr_angle>cos_test_angle)
+                                       if (cos_rcvr_angle>=cos_test_angle)
                                                block=1;
                                }
 
-                               /* At this point, we have the elevation angle
-                                  to the first obstruction (if it exists). */
+                               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
@@ -2541,34 +2846,32 @@ void PlotLRPath(struct site source, struct site destination, FILE *fd)
                           shortest distance terrain can play a role in
                           path loss. */
  
-                       elev_l[0]=y-1;  /* (number of points - 1) */
+                       elev[0]=y-1;  /* (number of points - 1) */
 
                        /* Distance between elevation samples */
-                       elev_l[1]=METERS_PER_MILE*(path.distance[y]-path.distance[y-1]);
 
-                       point_to_point(elev_l,source.alt*METERS_PER_FOOT, 
+                       elev[1]=METERS_PER_MILE*(path.distance[y]-path.distance[y-1]);
+
+                       point_to_point(elev,source.alt*METERS_PER_FOOT, 
                        destination.alt*METERS_PER_FOOT, LR.eps_dielect,
                        LR.sgm_conductivity, LR.eno_ns_surfref, LR.frq_mhz,
                        LR.radio_climate, LR.pol, LR.conf, LR.rel, loss,
                        strmode, errnum);
 
-                       if (block)
-                               elevation=((acos(cos_test_angle))/deg2rad)-90.0;
-
-                       else
-                               elevation=((acos(cos_xmtr_angle))/deg2rad)-90.0;
-
                        temp.lat=path.lat[y];
                        temp.lon=path.lon[y];
 
                        azimuth=(Azimuth(source,temp));
 
                        if (fd!=NULL)
-                       {
-                               /* Write path loss data to output file */
+                               fprintf(fd,"%.7f, %.7f, %.3f, %.3f, ",path.lat[y], path.lon[y], azimuth, elevation);
 
-                               fprintf(fd,"%.7f, %.7f, %.3f, %.3f, %.2f\n",path.lat[y], path.lon[y], azimuth, elevation, loss);
-                       }
+                       /* 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)
+                               fprintf(fd,"%.2f",loss);
 
                        /* Integrate the antenna's radiation
                           pattern into the overall path loss. */
@@ -2588,25 +2891,92 @@ void PlotLRPath(struct site source, struct site destination, FILE *fd)
                                }
                        }
 
-                       if (loss>225.0)
-                               loss=225.0;
+                       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));
 
-                       if (loss<75.0)
-                               loss=75.0;
+                                       dBm=10.0*(log10(rxp*1000.0));
 
-                       loss-=75.0;
-                       loss/=10.0;
-                       loss+=1.0;
-               
-                       OrMask(path.lat[y],path.lon[y],((unsigned char)(loss))<<3);
-               }
+                                       if (fd!=NULL)
+                                               fprintf(fd,"%.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)
+                                               fprintf(fd,"%.3f",field_strength);
+                               }
+                       }
+
+                       else
+                       {
+                               if (loss>255)
+                                       ifs=255;
+                               else
+                                       ifs=(int)rint(loss);
+
+                               ofs=GetSignal(path.lat[y],path.lon[y]);
 
-               else if (GetMask(path.lat[y],path.lon[y])==0 && path.distance[y]>max_range)
-                       OrMask(path.lat[y],path.lon[y],1);
+                               if (ofs<ifs && ofs!=0)
+                                       ifs=ofs;
+
+                               PutSignal(path.lat[y],path.lon[y],(unsigned char)ifs);
+                       }
+
+                       if (fd!=NULL)
+                       {
+                               if (block)
+                                       fprintf(fd," *");
+
+                               fprintf(fd,"\n");
+                       }
+
+                       /* 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));
+               }
        }
 }
 
-void PlotCoverage(struct site source, double altitude)
+void PlotLOSMap(struct site source, double altitude)
 {
        /* This function performs a 360 degree sweep around the
           transmitter site (source location), and plots the
@@ -2617,18 +2987,11 @@ void PlotCoverage(struct site source, double altitude)
           of a topographic map when the WritePPM() function
           is later invoked. */
 
-       float lat, lon, one_pixel;
-       static unsigned char mask_value;
-       int z, count;
+       int y, z, count;
        struct site edge;
        unsigned char symbol[4], x;
-
-       /* Initialize mask_value */
-
-       if (mask_value!=8 && mask_value!=16 && mask_value!=32)
-               mask_value=1;
-
-       one_pixel=1.0/1200.0;
+       double lat, lon, minwest, maxnorth, th;
+       static unsigned char mask_value=1;
 
        symbol[0]='.';
        symbol[1]='o';
@@ -2637,15 +3000,25 @@ void PlotCoverage(struct site source, double altitude)
 
        count=0;        
 
-       fprintf(stdout,"\nComputing line-of-sight coverage of %s with an RX antenna\nat %.2f %s AGL:\n\n 0%c to  25%c ",source.name,metric?altitude*METERS_PER_FOOT:altitude,metric?"meters":"feet",37,37);
+       fprintf(stdout,"\nComputing line-of-sight coverage of \"%s\" with an RX antenna\nat %.2f %s AGL",source.name,metric?altitude*METERS_PER_FOOT:altitude,metric?"meters":"feet");
+
+       if (clutter>0.0)
+               fprintf(stdout," and %.2f %s of ground clutter",metric?clutter*METERS_PER_FOOT:clutter,metric?"meters":"feet");
+
+       fprintf(stdout,"...\n\n 0%c to  25%c ",37,37);
        fflush(stdout);
 
-       /* 18.75=1200 pixels/degree divided by 64 loops
-          per progress indicator symbol (.oOo) printed. */
+       /* th=pixels/degree divided by 64 loops per
+          progress indicator symbol (.oOo) printed. */
+       
+       th=ppd/64.0;
+
+       z=(int)(th*ReduceAngle(max_west-min_west));
 
-       z=(int)(18.75*ReduceAngle(max_west-min_west));
+       minwest=dpp+(double)min_west;
+       maxnorth=(double)max_north-dpp;
 
-       for (lon=min_west, x=0; (LonDiff(lon,max_west)<=0.0); lon+=one_pixel)
+       for (lon=minwest, x=0, y=0; (LonDiff(lon,(double)max_west)<=0.0); y++, lon=minwest+(dpp*(double)y))
        {
                if (lon>=360.0)
                        lon-=360.0;
@@ -2674,9 +3047,9 @@ void PlotCoverage(struct site source, double altitude)
        fprintf(stdout,"\n25%c to  50%c ",37,37);
        fflush(stdout);
        
-       z=(int)(18.75*(max_north-min_north));
+       z=(int)(th*(double)(max_north-min_north));
 
-       for (lat=max_north, x=0; lat>=min_north; lat-=one_pixel)
+       for (lat=maxnorth, x=0, y=0; lat>=(double)min_north; y++, lat=maxnorth-(dpp*(double)y))
        {
                edge.lat=lat;
                edge.lon=min_west;
@@ -2702,9 +3075,9 @@ void PlotCoverage(struct site source, double altitude)
        fprintf(stdout,"\n50%c to  75%c ",37,37);
        fflush(stdout);
 
-       z=(int)(18.75*ReduceAngle(max_west-min_west));
+       z=(int)(th*ReduceAngle(max_west-min_west));
 
-       for (lon=min_west, x=0; (LonDiff(lon,max_west)<=0.0); lon+=one_pixel)
+       for (lon=minwest, x=0, y=0; (LonDiff(lon,(double)max_west)<=0.0); y++, lon=minwest+(dpp*(double)y))
        {
                if (lon>=360.0)
                        lon-=360.0;
@@ -2733,9 +3106,9 @@ void PlotCoverage(struct site source, double altitude)
        fprintf(stdout,"\n75%c to 100%c ",37,37);
        fflush(stdout);
        
-       z=(int)(18.75*(max_north-min_north));
+       z=(int)(th*(double)(max_north-min_north));
 
-       for (lat=min_north, x=0; lat<=max_north; lat+=one_pixel)
+       for (lat=(double)min_north, x=0, y=0; lat<(double)max_north; y++, lat=(double)min_north+(dpp*(double)y))
        {
                edge.lat=lat;
                edge.lon=max_west;
@@ -2785,16 +3158,18 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
           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 WritePPMLR() function
-          is later invoked. */
+          of a topographic map when the WritePPMLR() or
+          WritePPMSS() functions are later invoked. */
 
-       int z, count;
+       int y, z, count;
        struct site edge;
-       float lat, lon, one_pixel;
-       unsigned char symbol[4], x;
+       double lat, lon, minwest, maxnorth, th;
+       unsigned char x, symbol[4];
+       static unsigned char mask_value=1;
        FILE *fd=NULL;
 
-       one_pixel=1.0/1200.0;
+       minwest=dpp+(double)min_west;
+       maxnorth=(double)max_north-dpp;
 
        symbol[0]='.';
        symbol[1]='o';
@@ -2803,9 +3178,24 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
 
        count=0;
 
-       fprintf(stdout,"\nComputing Longley-Rice coverage of %s ", source.name);
+       fprintf(stdout,"\nComputing Longley-Rice ");
+
+       if (LR.erp==0.0)
+               fprintf(stdout,"path loss");
+       else
+       {
+               if (dbm)
+                       fprintf(stdout,"signal power level");
+               else
+                       fprintf(stdout,"field strength");
+       }
+       fprintf(stdout," contours of \"%s\"\nout to a radius of %.2f %s with an RX antenna at %.2f %s AGL",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)
+               fprintf(stdout,"\nand %.2f %s of ground clutter",metric?clutter*METERS_PER_FOOT:clutter,metric?"meters":"feet");
 
-       fprintf(stdout,"out to a radius\nof %.2f %s with an RX antenna at %.2f %s AGL:\n\n 0%c to  25%c ",metric?max_range*KM_PER_MILE:max_range,metric?"kilometers":"miles",metric?altitude*METERS_PER_FOOT:altitude,metric?"meters":"feet",37,37);
+       fprintf(stdout,"...\n\n 0%c to  25%c ",37,37);
        fflush(stdout);
 
        if (plo_filename[0]!=0)
@@ -2818,12 +3208,14 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
                fprintf(fd,"%d, %d\t; max_west, min_west\n%d, %d\t; max_north, min_north\n",max_west, min_west, max_north, min_north);
        }
 
-       /* 18.75=1200 pixels/degree divided by 64 loops
-          per progress indicator symbol (.oOo) printed. */
+       /* th=pixels/degree divided by 64 loops per
+          progress indicator symbol (.oOo) printed. */
+       
+       th=ppd/64.0;
 
-       z=(int)(18.75*ReduceAngle(max_west-min_west));
+       z=(int)(th*ReduceAngle(max_west-min_west));
 
-       for (lon=min_west, x=0; (LonDiff(lon,max_west)<=0.0); lon+=one_pixel)
+       for (lon=minwest, x=0, y=0; (LonDiff(lon,(double)max_west)<=0.0); y++, lon=minwest+(dpp*(double)y))
        {
                if (lon>=360.0)
                        lon-=360.0;
@@ -2832,7 +3224,7 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
                edge.lon=lon;
                edge.alt=altitude;
 
-               PlotLRPath(source,edge,fd);
+               PlotLRPath(source,edge,mask_value,fd);
                count++;
 
                if (count==z) 
@@ -2852,15 +3244,15 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
        fprintf(stdout,"\n25%c to  50%c ",37,37);
        fflush(stdout);
        
-       z=(int)(18.75*(max_north-min_north));
+       z=(int)(th*(double)(max_north-min_north));
 
-       for (lat=max_north, x=0; lat>=min_north; lat-=one_pixel)
+       for (lat=maxnorth, x=0, y=0; lat>=(double)min_north; y++, lat=maxnorth-(dpp*(double)y))
        {
                edge.lat=lat;
                edge.lon=min_west;
                edge.alt=altitude;
 
-               PlotLRPath(source,edge,fd);
+               PlotLRPath(source,edge,mask_value,fd);
                count++;
 
                if (count==z) 
@@ -2880,9 +3272,9 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
        fprintf(stdout,"\n50%c to  75%c ",37,37);
        fflush(stdout);
 
-       z=(int)(18.75*ReduceAngle(max_west-min_west));
+       z=(int)(th*ReduceAngle(max_west-min_west));
 
-       for (lon=min_west, x=0; (LonDiff(lon,max_west)<=0.0); lon+=one_pixel)
+       for (lon=minwest, x=0, y=0; (LonDiff(lon,(double)max_west)<=0.0); y++, lon=minwest+(dpp*(double)y))
        {
                if (lon>=360.0)
                        lon-=360.0;
@@ -2891,7 +3283,7 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
                edge.lon=lon;
                edge.alt=altitude;
 
-               PlotLRPath(source,edge,fd);
+               PlotLRPath(source,edge,mask_value,fd);
                count++;
 
                if (count==z)
@@ -2911,15 +3303,15 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
        fprintf(stdout,"\n75%c to 100%c ",37,37);
        fflush(stdout);
        
-       z=(int)(18.75*(max_north-min_north));
+       z=(int)(th*(double)(max_north-min_north));
 
-       for (lat=min_north, x=0; lat<=max_north; lat+=one_pixel)
+       for (lat=(double)min_north, x=0, y=0; lat<(double)max_north; y++, lat=(double)min_north+(dpp*(double)y))
        {
                edge.lat=lat;
                edge.lon=max_west;
                edge.alt=altitude;
 
-               PlotLRPath(source,edge,fd);
+               PlotLRPath(source,edge,mask_value,fd);
                count++;
 
                if (count==z)
@@ -2940,9 +3332,496 @@ void PlotLRMap(struct site source, double altitude, char *plo_filename)
 
        fprintf(stdout,"\nDone!\n");
        fflush(stdout);
+
+       if (mask_value<30)
+               mask_value++;
+}
+
+void LoadSignalColors(struct site xmtr)
+{
+       int x, y, ok, val[4];
+       char filename[255], string[80], *pointer=NULL, *s=NULL;
+       FILE *fd=NULL;
+
+       for (x=0; xmtr.filename[x]!='.' && xmtr.filename[x]!=0 && x<250; x++)
+               filename[x]=xmtr.filename[x];
+
+       filename[x]='.';
+       filename[x+1]='s';
+       filename[x+2]='c';
+       filename[x+3]='f';
+       filename[x+4]=0;
+
+       /* Default values */
+
+       region.level[0]=128;
+       region.color[0][0]=255;
+       region.color[0][1]=0;
+       region.color[0][2]=0;
+
+       region.level[1]=118;
+       region.color[1][0]=255;
+       region.color[1][1]=165;
+       region.color[1][2]=0;
+
+       region.level[2]=108;
+       region.color[2][0]=255;
+       region.color[2][1]=206;
+       region.color[2][2]=0;
+
+       region.level[3]=98;
+       region.color[3][0]=255;
+       region.color[3][1]=255;
+       region.color[3][2]=0;
+
+       region.level[4]=88;
+       region.color[4][0]=184;
+       region.color[4][1]=255;
+       region.color[4][2]=0;
+
+       region.level[5]=78;
+       region.color[5][0]=0;
+       region.color[5][1]=255;
+       region.color[5][2]=0;
+
+       region.level[6]=68;
+       region.color[6][0]=0;
+       region.color[6][1]=208;
+       region.color[6][2]=0;
+
+       region.level[7]=58;
+       region.color[7][0]=0;
+       region.color[7][1]=196;
+       region.color[7][2]=196;
+
+       region.level[8]=48;
+       region.color[8][0]=0;
+       region.color[8][1]=148;
+       region.color[8][2]=255;
+
+       region.level[9]=38;
+       region.color[9][0]=80;
+       region.color[9][1]=80;
+       region.color[9][2]=255;
+
+       region.level[10]=28;
+       region.color[10][0]=0;
+       region.color[10][1]=38;
+       region.color[10][2]=255;
+
+       region.level[11]=18;
+       region.color[11][0]=142;
+       region.color[11][1]=63;
+       region.color[11][2]=255;
+
+       region.level[12]=8;
+       region.color[12][0]=140;
+       region.color[12][1]=0;
+       region.color[12][2]=128;
+
+       region.levels=13;
+
+       fd=fopen("splat.scf","r");
+
+       if (fd==NULL)
+               fd=fopen(filename,"r");
+
+       if (fd==NULL)
+       {
+               fd=fopen(filename,"w");
+
+               fprintf(fd,"; SPLAT! Auto-generated Signal Color Definition (\"%s\") File\n",filename);
+               fprintf(fd,";\n; Format for the parameters held in this file is as follows:\n;\n");
+               fprintf(fd,";    dBuV/m: red, green, blue\n;\n");
+               fprintf(fd,"; ...where \"dBuV/m\" is the signal strength (in dBuV/m) and\n");
+               fprintf(fd,"; \"red\", \"green\", and \"blue\" are the corresponding RGB color\n");
+               fprintf(fd,"; definitions ranging from 0 to 255 for the region specified.\n");
+               fprintf(fd,";\n; The following parameters may be edited and/or expanded\n");
+               fprintf(fd,"; for future runs of SPLAT!  A total of 32 contour regions\n");
+               fprintf(fd,"; may be defined in this file.\n;\n;\n");
+
+               for (x=0; x<region.levels; x++)
+                       fprintf(fd,"%3d: %3d, %3d, %3d\n",region.level[x], region.color[x][0], region.color[x][1], region.color[x][2]);
+
+               fclose(fd);
+       }
+
+       else
+       {
+               x=0;
+               s=fgets(string,80,fd);
+
+               while (x<32 && feof(fd)==0)
+               {
+                       pointer=strchr(string,';');
+
+                       if (pointer!=NULL)
+                               *pointer=0;
+
+                       ok=sscanf(string,"%d: %d, %d, %d", &val[0], &val[1], &val[2], &val[3]);
+
+                       if (ok==4)
+                       {
+                               for (y=0; y<4; y++)
+                               {
+                                       if (val[y]>255)
+                                               val[y]=255;
+
+                                       if (val[y]<0)
+                                               val[y]=0;
+                               }
+       
+                               region.level[x]=val[0];
+                               region.color[x][0]=val[1];
+                               region.color[x][1]=val[2];
+                               region.color[x][2]=val[3];
+                               x++;
+                       }
+
+                       s=fgets(string,80,fd);
+               }
+
+               fclose(fd);
+               region.levels=x;
+       }
+}
+
+void LoadLossColors(struct site xmtr)
+{
+       int x, y, ok, val[4];
+       char filename[255], string[80], *pointer=NULL, *s=NULL;
+       FILE *fd=NULL;
+
+       for (x=0; xmtr.filename[x]!='.' && xmtr.filename[x]!=0 && x<250; x++)
+               filename[x]=xmtr.filename[x];
+
+       filename[x]='.';
+       filename[x+1]='l';
+       filename[x+2]='c';
+       filename[x+3]='f';
+       filename[x+4]=0;
+
+       /* Default values */
+
+       region.level[0]=80;
+       region.color[0][0]=255;
+       region.color[0][1]=0;
+       region.color[0][2]=0;
+
+       region.level[1]=90;
+       region.color[1][0]=255;
+       region.color[1][1]=128;
+       region.color[1][2]=0;
+
+       region.level[2]=100;
+       region.color[2][0]=255;
+       region.color[2][1]=165;
+       region.color[2][2]=0;
+
+       region.level[3]=110;
+       region.color[3][0]=255;
+       region.color[3][1]=206;
+       region.color[3][2]=0;
+
+       region.level[4]=120;
+       region.color[4][0]=255;
+       region.color[4][1]=255;
+       region.color[4][2]=0;
+
+       region.level[5]=130;
+       region.color[5][0]=184;
+       region.color[5][1]=255;
+       region.color[5][2]=0;
+
+       region.level[6]=140;
+       region.color[6][0]=0;
+       region.color[6][1]=255;
+       region.color[6][2]=0;
+
+       region.level[7]=150;
+       region.color[7][0]=0;
+       region.color[7][1]=208;
+       region.color[7][2]=0;
+
+       region.level[8]=160;
+       region.color[8][0]=0;
+       region.color[8][1]=196;
+       region.color[8][2]=196;
+
+       region.level[9]=170;
+       region.color[9][0]=0;
+       region.color[9][1]=148;
+       region.color[9][2]=255;
+
+       region.level[10]=180;
+       region.color[10][0]=80;
+       region.color[10][1]=80;
+       region.color[10][2]=255;
+
+       region.level[11]=190;
+       region.color[11][0]=0;
+       region.color[11][1]=38;
+       region.color[11][2]=255;
+
+       region.level[12]=200;
+       region.color[12][0]=142;
+       region.color[12][1]=63;
+       region.color[12][2]=255;
+
+       region.level[13]=210;
+       region.color[13][0]=196;
+       region.color[13][1]=54;
+       region.color[13][2]=255;
+
+       region.level[14]=220;
+       region.color[14][0]=255;
+       region.color[14][1]=0;
+       region.color[14][2]=255;
+
+       region.level[15]=230;
+       region.color[15][0]=255;
+       region.color[15][1]=194;
+       region.color[15][2]=204;
+
+       region.levels=16;
+
+       fd=fopen("splat.lcf","r");
+
+       if (fd==NULL)
+               fd=fopen(filename,"r");
+
+       if (fd==NULL)
+       {
+               fd=fopen(filename,"w");
+
+               fprintf(fd,"; SPLAT! Auto-generated Path-Loss Color Definition (\"%s\") File\n",filename);
+               fprintf(fd,";\n; Format for the parameters held in this file is as follows:\n;\n");
+               fprintf(fd,";    dB: red, green, blue\n;\n");
+               fprintf(fd,"; ...where \"dB\" is the path loss (in dB) and\n");
+               fprintf(fd,"; \"red\", \"green\", and \"blue\" are the corresponding RGB color\n");
+               fprintf(fd,"; definitions ranging from 0 to 255 for the region specified.\n");
+               fprintf(fd,";\n; The following parameters may be edited and/or expanded\n");
+               fprintf(fd,"; for future runs of SPLAT!  A total of 32 contour regions\n");
+               fprintf(fd,"; may be defined in this file.\n;\n;\n");
+
+               for (x=0; x<region.levels; x++)
+                       fprintf(fd,"%3d: %3d, %3d, %3d\n",region.level[x], region.color[x][0], region.color[x][1], region.color[x][2]);
+
+               fclose(fd);
+       }
+
+       else
+       {
+               x=0;
+               s=fgets(string,80,fd);
+
+               while (x<32 && feof(fd)==0)
+               {
+                       pointer=strchr(string,';');
+
+                       if (pointer!=NULL)
+                               *pointer=0;
+
+                       ok=sscanf(string,"%d: %d, %d, %d", &val[0], &val[1], &val[2], &val[3]);
+
+                       if (ok==4)
+                       {
+                               for (y=0; y<4; y++)
+                               {
+                                       if (val[y]>255)
+                                               val[y]=255;
+
+                                       if (val[y]<0)
+                                               val[y]=0;
+                               }
+       
+                               region.level[x]=val[0];
+                               region.color[x][0]=val[1];
+                               region.color[x][1]=val[2];
+                               region.color[x][2]=val[3];
+                               x++;
+                       }
+
+                       s=fgets(string,80,fd);
+               }
+
+               fclose(fd);
+               region.levels=x;
+       }
+}
+
+void LoadDBMColors(struct site xmtr)
+{
+       int x, y, ok, val[4];
+       char filename[255], string[80], *pointer=NULL, *s=NULL;
+       FILE *fd=NULL;
+
+       for (x=0; xmtr.filename[x]!='.' && xmtr.filename[x]!=0 && x<250; x++)
+               filename[x]=xmtr.filename[x];
+
+       filename[x]='.';
+       filename[x+1]='d';
+       filename[x+2]='c';
+       filename[x+3]='f';
+       filename[x+4]=0;
+
+       /* Default values */
+
+       region.level[0]=0;
+       region.color[0][0]=255;
+       region.color[0][1]=0;
+       region.color[0][2]=0;
+
+       region.level[1]=-10;
+       region.color[1][0]=255;
+       region.color[1][1]=128;
+       region.color[1][2]=0;
+
+       region.level[2]=-20;
+       region.color[2][0]=255;
+       region.color[2][1]=165;
+       region.color[2][2]=0;
+
+       region.level[3]=-30;
+       region.color[3][0]=255;
+       region.color[3][1]=206;
+       region.color[3][2]=0;
+
+       region.level[4]=-40;
+       region.color[4][0]=255;
+       region.color[4][1]=255;
+       region.color[4][2]=0;
+
+       region.level[5]=-50;
+       region.color[5][0]=184;
+       region.color[5][1]=255;
+       region.color[5][2]=0;
+
+       region.level[6]=-60;
+       region.color[6][0]=0;
+       region.color[6][1]=255;
+       region.color[6][2]=0;
+
+       region.level[7]=-70;
+       region.color[7][0]=0;
+       region.color[7][1]=208;
+       region.color[7][2]=0;
+
+       region.level[8]=-80;
+       region.color[8][0]=0;
+       region.color[8][1]=196;
+       region.color[8][2]=196;
+
+       region.level[9]=-90;
+       region.color[9][0]=0;
+       region.color[9][1]=148;
+       region.color[9][2]=255;
+
+       region.level[10]=-100;
+       region.color[10][0]=80;
+       region.color[10][1]=80;
+       region.color[10][2]=255;
+
+       region.level[11]=-110;
+       region.color[11][0]=0;
+       region.color[11][1]=38;
+       region.color[11][2]=255;
+
+       region.level[12]=-120;
+       region.color[12][0]=142;
+       region.color[12][1]=63;
+       region.color[12][2]=255;
+
+       region.level[13]=-130;
+       region.color[13][0]=196;
+       region.color[13][1]=54;
+       region.color[13][2]=255;
+
+       region.level[14]=-140;
+       region.color[14][0]=255;
+       region.color[14][1]=0;
+       region.color[14][2]=255;
+
+       region.level[15]=-150;
+       region.color[15][0]=255;
+       region.color[15][1]=194;
+       region.color[15][2]=204;
+
+       region.levels=16;
+
+       fd=fopen("splat.dcf","r");
+
+       if (fd==NULL)
+               fd=fopen(filename,"r");
+
+       if (fd==NULL)
+       {
+               fd=fopen(filename,"w");
+
+               fprintf(fd,"; SPLAT! Auto-generated DBM Signal Level Color Definition (\"%s\") File\n",filename);
+               fprintf(fd,";\n; Format for the parameters held in this file is as follows:\n;\n");
+               fprintf(fd,";    dBm: red, green, blue\n;\n");
+               fprintf(fd,"; ...where \"dBm\" is the received signal power level between +40 dBm\n");
+               fprintf(fd,"; and -200 dBm, and \"red\", \"green\", and \"blue\" are the corresponding\n");
+               fprintf(fd,"; RGB color definitions ranging from 0 to 255 for the region specified.\n");
+               fprintf(fd,";\n; The following parameters may be edited and/or expanded\n");
+               fprintf(fd,"; for future runs of SPLAT!  A total of 32 contour regions\n");
+               fprintf(fd,"; may be defined in this file.\n;\n;\n");
+
+               for (x=0; x<region.levels; x++)
+                       fprintf(fd,"%+4d: %3d, %3d, %3d\n",region.level[x], region.color[x][0], region.color[x][1], region.color[x][2]);
+
+               fclose(fd);
+       }
+
+       else
+       {
+               x=0;
+               s=fgets(string,80,fd);
+
+               while (x<32 && feof(fd)==0)
+               {
+                       pointer=strchr(string,';');
+
+                       if (pointer!=NULL)
+                               *pointer=0;
+
+                       ok=sscanf(string,"%d: %d, %d, %d", &val[0], &val[1], &val[2], &val[3]);
+
+                       if (ok==4)
+                       {
+                               if (val[0]<-200)
+                                       val[0]=-200;
+
+                               if (val[0]>+40)
+                                       val[0]=+40;
+
+                               region.level[x]=val[0];
+
+                               for (y=1; y<4; y++)
+                               {
+                                       if (val[y]>255)
+                                               val[y]=255;
+
+                                       if (val[y]<0)
+                                               val[y]=0;
+                               }
+       
+                               region.color[x][0]=val[1];
+                               region.color[x][1]=val[2];
+                               region.color[x][2]=val[3];
+                               x++;
+                       }
+
+                       s=fgets(string,80,fd);
+               }
+
+               fclose(fd);
+               region.levels=x;
+       }
 }
 
-void WritePPM(char *filename, unsigned char geo)
+void WritePPM(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites)
 {
        /* This function generates a topographic map in Portable Pix Map
           (PPM) format based on logarithmically scaled topology data,
@@ -2951,52 +3830,134 @@ void WritePPM(char *filename, unsigned char geo)
           from its representation in dem[][] so that north points
           up and east points right in the image generated. */
 
-       char mapfile[255], geofile[255];
+       char mapfile[255], geofile[255], kmlfile[255];
        unsigned char found, mask;
-       unsigned width, height, output;
-       int indx, x, y, x0=0, y0=0, minlat, minlon;
-       float lat, lon, one_pixel, conversion, one_over_gamma;
+       unsigned width, height, terrain;
+       int indx, x, y, x0=0, y0=0;
+       double lat, lon, conversion, one_over_gamma,
+       north, south, east, west, minwest;
        FILE *fd;
 
-       one_pixel=1.0/1200.0;
        one_over_gamma=1.0/GAMMA;
        conversion=255.0/pow((double)(max_elevation-min_elevation),one_over_gamma);
 
-       width=(unsigned)(1200*ReduceAngle(max_west-min_west));
-       height=(unsigned)(1200*ReduceAngle(max_north-min_north));
+       width=(unsigned)(ippd*ReduceAngle(max_west-min_west));
+       height=(unsigned)(ippd*ReduceAngle(max_north-min_north));
 
        if (filename[0]==0)
-               strncpy(mapfile, "map.ppm\0",8);
-       else
        {
-               for (x=0; filename[x]!='.' && filename[x]!=0 && x<250; x++)
-               {
-                       mapfile[x]=filename[x];
-                       geofile[x]=filename[x];
-               }
+               strncpy(filename, xmtr[0].filename,254);
+               filename[strlen(filename)-4]=0;  /* Remove .qth */
+       }
 
-               mapfile[x]='.';
-               geofile[x]='.';
-               mapfile[x+1]='p';
-               geofile[x+1]='g';
-               mapfile[x+2]='p';
-               geofile[x+2]='e';
-               mapfile[x+3]='m';
-               geofile[x+3]='o';
-               mapfile[x+4]=0;
-               geofile[x+4]=0;
+       y=strlen(filename);
+
+       if (y>4)
+       {
+               if (filename[y-1]=='m' && filename[y-2]=='p' && filename[y-3]=='p' && filename[y-4]=='.')
+                       y-=4;
+       }
+
+       for (x=0; x<y; x++)
+       {
+               mapfile[x]=filename[x];
+               geofile[x]=filename[x];
+               kmlfile[x]=filename[x];
        }
 
-       if (geo)
+       mapfile[x]='.';
+       geofile[x]='.';
+       kmlfile[x]='.';
+       mapfile[x+1]='p';
+       geofile[x+1]='g';
+       kmlfile[x+1]='k';
+       mapfile[x+2]='p';
+       geofile[x+2]='e';
+       kmlfile[x+2]='m';
+       mapfile[x+3]='m';
+       geofile[x+3]='o';
+       kmlfile[x+3]='l';
+       mapfile[x+4]=0;
+       geofile[x+4]=0;
+       kmlfile[x+4]=0;
+
+       minwest=((double)min_west)+dpp;
+
+       if (minwest>360.0)
+               minwest-=360.0;
+
+       north=(double)max_north-dpp;
+       south=(double)min_north;
+       east=(minwest<180.0?-minwest:360.0-min_west);
+       west=(double)(max_west<180?-max_west:360-max_west);
+
+       if (kml==0 && geo)
        {
                fd=fopen(geofile,"wb");
 
                fprintf(fd,"FILENAME\t%s\n",mapfile);
                fprintf(fd,"#\t\tX\tY\tLong\t\tLat\n");
-               fprintf(fd,"TIEPOINT\t0\t0\t%d.000\t\t%d.000\n",(max_west<180?-max_west:360-max_west),max_north);
-               fprintf(fd,"TIEPOINT\t%u\t%u\t%d.000\t\t%d.000\n",width-1,height-1,(min_west<180?-min_west:360-min_west),min_north);
+               fprintf(fd,"TIEPOINT\t0\t0\t%.3f\t\t%.3f\n",west,north);
+               fprintf(fd,"TIEPOINT\t%u\t%u\t%.3f\t\t%.3f\n",width-1,height-1,east,south);
                fprintf(fd,"IMAGESIZE\t%u\t%u\n",width,height);
-               fprintf(fd,"#\n# Auto Generated by SPLAT! v%s\n#\n",splat_version);
+               fprintf(fd,"#\n# Auto Generated by %s v%s\n#\n",splat_name,splat_version);
+
+               fclose(fd);
+       }
+
+       if (kml && geo==0)
+       {
+               fd=fopen(kmlfile,"wb");
+
+               fprintf(fd,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               fprintf(fd,"<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+               fprintf(fd,"  <Folder>\n");
+               fprintf(fd,"   <name>%s</name>\n",splat_name);
+               fprintf(fd,"     <description>Line-of-Sight Overlay</description>\n");
+               fprintf(fd,"       <GroundOverlay>\n");
+               fprintf(fd,"         <name>%s Line-of-Sight Overlay</name>\n",splat_name);
+               fprintf(fd,"           <description>SPLAT! Coverage</description>\n");
+               fprintf(fd,"            <Icon>\n");
+               fprintf(fd,"              <href>%s</href>\n",mapfile);
+               fprintf(fd,"            </Icon>\n");
+               fprintf(fd,"            <opacity>128</opacity>\n");
+               fprintf(fd,"            <LatLonBox>\n");
+               fprintf(fd,"               <north>%.5f</north>\n",north);
+               fprintf(fd,"               <south>%.5f</south>\n",south);
+               fprintf(fd,"               <east>%.5f</east>\n",east);
+               fprintf(fd,"               <west>%.5f</west>\n",west);
+               fprintf(fd,"               <rotation>0.0</rotation>\n");
+               fprintf(fd,"            </LatLonBox>\n");
+               fprintf(fd,"       </GroundOverlay>\n");
+
+               for (x=0; x<txsites; x++)
+               {
+                       fprintf(fd,"     <Placemark>\n");
+                       fprintf(fd,"       <name>%s</name>\n",xmtr[x].name);
+                       fprintf(fd,"       <visibility>1</visibility>\n");
+                       fprintf(fd,"       <Style>\n");
+                       fprintf(fd,"       <IconStyle>\n");
+                       fprintf(fd,"        <Icon>\n");
+                       fprintf(fd,"          <href>root://icons/palette-5.png</href>\n");
+                       fprintf(fd,"          <x>224</x>\n");
+                       fprintf(fd,"          <y>224</y>\n");
+                       fprintf(fd,"          <w>32</w>\n");
+                       fprintf(fd,"          <h>32</h>\n");
+                       fprintf(fd,"        </Icon>\n");
+                       fprintf(fd,"       </IconStyle>\n");
+                       fprintf(fd,"       </Style>\n");
+                       fprintf(fd,"      <Point>\n");
+                       fprintf(fd,"        <extrude>1</extrude>\n");
+                       fprintf(fd,"        <altitudeMode>relativeToGround</altitudeMode>\n");
+                       fprintf(fd,"        <coordinates>%f,%f,%f</coordinates>\n",(xmtr[x].lon<180.0?-xmtr[x].lon:360.0-xmtr[x].lon), xmtr[x].lat, xmtr[x].alt);
+                       fprintf(fd,"      </Point>\n");
+                       fprintf(fd,"     </Placemark>\n");
+               }
+
+
+
+               fprintf(fd,"  </Folder>\n");
+               fprintf(fd,"</kml>\n");
 
                fclose(fd);
        }
@@ -3004,32 +3965,29 @@ void WritePPM(char *filename, unsigned char geo)
        fd=fopen(mapfile,"wb");
 
        fprintf(fd,"P6\n%u %u\n255\n",width,height);
-
        fprintf(stdout,"\nWriting \"%s\" (%ux%u pixmap image)... ",mapfile,width,height);
        fflush(stdout);
 
-       for (y=0, lat=((double)max_north)-one_pixel; y<(int)height; y++, lat-=one_pixel)
+       for (y=0, lat=north; y<(int)height; y++, lat=north-(dpp*(double)y))
        {
-               minlat=(int)floor(lat);
-
-               for (x=0, lon=((double)max_west)-one_pixel; x<(int)width; x++, lon-=one_pixel)
+               for (x=0, lon=max_west; x<(int)width; x++, lon=(double)max_west-(dpp*(double)x))
                {
                        if (lon<0.0)
                                lon+=360.0;
 
-                       minlon=(int)floor(lon);
+                       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+                       {
+                               x0=(int)rint(ppd*(lat-(double)dem[indx].min_north));
+                               y0=mpi-(int)rint(ppd*(LonDiff((double)dem[indx].max_west,lon)));
 
-                       for (indx=0, found=0; indx<MAXSLOTS && found==0;)
-                               if (minlat==dem[indx].min_north && minlon==dem[indx].min_west)
+                               if (x0>=0 && x0<=mpi && y0>=0 && y0<=mpi)
                                        found=1;
                                else
                                        indx++;
+                       }
 
                        if (found)
                        {
-                               x0=(int)(1199.0*(lat-floor(lat)));
-                               y0=(int)(1199.0*(lon-floor(lon)));
-
                                mask=dem[indx].mask[x0][y0];
 
                                if (mask&2)
@@ -3118,14 +4076,19 @@ void WritePPM(char *filename, unsigned char geo)
                                        break;
 
                                        default:
-                                       /* Water: Medium Blue */
-                                       if (dem[indx].data[x0][y0]==0)
-                                               fprintf(fd,"%c%c%c",0,0,170);
+                                       if (ngs)  /* No terrain */
+                                               fprintf(fd,"%c%c%c",255,255,255);
                                        else
                                        {
-                                               /* Elevation: Greyscale */
-                                               output=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
-                                               fprintf(fd,"%c%c%c",output,output,output);
+                                               /* Sea-level: Medium Blue */
+                                               if (dem[indx].data[x0][y0]==0)
+                                                       fprintf(fd,"%c%c%c",0,0,170);
+                                               else
+                                               {
+                                                       /* Elevation: Greyscale */
+                                                       terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                       fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                               }
                                        }
                                }
                        }
@@ -3145,7 +4108,7 @@ void WritePPM(char *filename, unsigned char geo)
        fflush(stdout);
 }
 
-void WritePPMLR(char *filename, unsigned char geo)
+void WritePPMLR(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites)
 {
        /* This function generates a topographic map in Portable Pix Map
           (PPM) format based on the content of flags held in the mask[][] 
@@ -3153,98 +4116,211 @@ void WritePPMLR(char *filename, unsigned char geo)
           90 degrees from its representation in dem[][] so that north
           points up and east points right in the image generated. */
 
-       char mapfile[255], geofile[255];
-       unsigned width, height, output;
+       char mapfile[255], geofile[255], kmlfile[255];
+       unsigned width, height, red, green, blue, terrain=0;
        unsigned char found, mask, cityorcounty;
-       int indx, x, y, t, t2, x0, y0, minlat, minlon, loss;
-       float lat, lon, one_pixel, conversion, one_over_gamma;
+       int indx, x, y, z, colorwidth, x0, y0, loss, level,
+           hundreds, tens, units, match;
+       double lat, lon, conversion, one_over_gamma,
+       north, south, east, west, minwest;
        FILE *fd;
 
-       one_pixel=1.0/1200.0;
        one_over_gamma=1.0/GAMMA;
        conversion=255.0/pow((double)(max_elevation-min_elevation),one_over_gamma);
 
-       width=(unsigned)(1200*ReduceAngle(max_west-min_west));
-       height=(unsigned)(1200*ReduceAngle(max_north-min_north));
+       width=(unsigned)(ippd*ReduceAngle(max_west-min_west));
+       height=(unsigned)(ippd*ReduceAngle(max_north-min_north));
+
+       LoadLossColors(xmtr[0]);
 
        if (filename[0]==0)
-               strncpy(mapfile, "map.ppm\0",8);
-       else
        {
-               for (x=0; filename[x]!='.' && filename[x]!=0 && x<250; x++)
-               {
-                       mapfile[x]=filename[x];
-                       geofile[x]=filename[x];
-               }
+               strncpy(filename, xmtr[0].filename,254);
+               filename[strlen(filename)-4]=0;  /* Remove .qth */
+       }
+
+       y=strlen(filename);
+
+       if (y>4)
+       {
+               if (filename[y-1]=='m' && filename[y-2]=='p' && filename[y-3]=='p' && filename[y-4]=='.')
+                       y-=4;
+       }
 
-               mapfile[x]='.';
-               geofile[x]='.';
-               mapfile[x+1]='p';
-               geofile[x+1]='g';
-               mapfile[x+2]='p';
-               geofile[x+2]='e';
-               mapfile[x+3]='m';
-               geofile[x+3]='o';
-               mapfile[x+4]=0;
-               geofile[x+4]=0;
+       for (x=0; x<y; x++)
+       {
+               mapfile[x]=filename[x];
+               geofile[x]=filename[x];
+               kmlfile[x]=filename[x];
        }
 
-       if (geo)
+       mapfile[x]='.';
+       geofile[x]='.';
+       kmlfile[x]='.';
+       mapfile[x+1]='p';
+       geofile[x+1]='g';
+       kmlfile[x+1]='k';
+       mapfile[x+2]='p';
+       geofile[x+2]='e';
+       kmlfile[x+2]='m';
+       mapfile[x+3]='m';
+       geofile[x+3]='o';
+       kmlfile[x+3]='l';
+       mapfile[x+4]=0;
+       geofile[x+4]=0;
+       kmlfile[x+4]=0;
+
+       minwest=((double)min_west)+dpp;
+
+       if (minwest>360.0)
+               minwest-=360.0;
+
+       north=(double)max_north-dpp;
+
+       if (kml || geo)
+               south=(double)min_north;        /* No bottom legend */
+       else
+               south=(double)min_north-(30.0/ppd); /* 30 pixels for bottom legend */
+
+       east=(minwest<180.0?-minwest:360.0-min_west);
+       west=(double)(max_west<180?-max_west:360-max_west);
+
+       if (kml==0 && geo)
        {
                fd=fopen(geofile,"wb");
 
                fprintf(fd,"FILENAME\t%s\n",mapfile);
                fprintf(fd,"#\t\tX\tY\tLong\t\tLat\n");
-               fprintf(fd,"TIEPOINT\t0\t0\t%d.000\t\t%d.000\n",(max_west<180?-max_west:360-max_west),max_north);
-               fprintf(fd,"TIEPOINT\t%u\t%u\t%d.000\t\t%.3f\n",width-1,height+29,(min_west<180?-min_west:360-min_west),(double)(min_north-0.025));
-               fprintf(fd,"IMAGESIZE\t%u\t%u\n",width,height+30);
-               fprintf(fd,"#\n# Auto Generated by SPLAT! v%s\n#\n",splat_version);
+               fprintf(fd,"TIEPOINT\t0\t0\t%.3f\t\t%.3f\n",west,north);
+
+               fprintf(fd,"TIEPOINT\t%u\t%u\t%.3f\t\t%.3f\n",width-1,height-1,east,south);
+               fprintf(fd,"IMAGESIZE\t%u\t%u\n",width,height);
+
+               fprintf(fd,"#\n# Auto Generated by %s v%s\n#\n",splat_name,splat_version);
 
                fclose(fd);
        }
 
-       fd=fopen(mapfile,"wb");
+       if (kml && geo==0)
+       {
+               fd=fopen(kmlfile,"wb");
+
+               fprintf(fd,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               fprintf(fd,"<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+               fprintf(fd,"<!-- Generated by %s Version %s -->\n",splat_name,splat_version);
+               fprintf(fd,"  <Folder>\n");
+               fprintf(fd,"   <name>%s</name>\n",splat_name);
+               fprintf(fd,"     <description>%s Transmitter Path Loss Overlay</description>\n",xmtr[0].name);
+               fprintf(fd,"       <GroundOverlay>\n");
+               fprintf(fd,"         <name>SPLAT! Path Loss Overlay</name>\n");
+               fprintf(fd,"           <description>SPLAT! Coverage</description>\n");
+               fprintf(fd,"            <Icon>\n");
+               fprintf(fd,"              <href>%s</href>\n",mapfile);
+               fprintf(fd,"            </Icon>\n");
+               fprintf(fd,"            <opacity>128</opacity>\n");
+               fprintf(fd,"            <LatLonBox>\n");
+               fprintf(fd,"               <north>%.5f</north>\n",north);
+               fprintf(fd,"               <south>%.5f</south>\n",south);
+               fprintf(fd,"               <east>%.5f</east>\n",east);
+               fprintf(fd,"               <west>%.5f</west>\n",west);
+               fprintf(fd,"               <rotation>0.0</rotation>\n");
+               fprintf(fd,"            </LatLonBox>\n");
+               fprintf(fd,"       </GroundOverlay>\n");
 
-       fprintf(fd,"P6\n%u %u\n255\n",width,height+30);
+               for (x=0; x<txsites; x++)
+               {
+                       fprintf(fd,"     <Placemark>\n");
+                       fprintf(fd,"       <name>%s</name>\n",xmtr[x].name);
+                       fprintf(fd,"       <visibility>1</visibility>\n");
+                       fprintf(fd,"       <Style>\n");
+                       fprintf(fd,"       <IconStyle>\n");
+                       fprintf(fd,"        <Icon>\n");
+                       fprintf(fd,"          <href>root://icons/palette-5.png</href>\n");
+                       fprintf(fd,"          <x>224</x>\n");
+                       fprintf(fd,"          <y>224</y>\n");
+                       fprintf(fd,"          <w>32</w>\n");
+                       fprintf(fd,"          <h>32</h>\n");
+                       fprintf(fd,"        </Icon>\n");
+                       fprintf(fd,"       </IconStyle>\n");
+                       fprintf(fd,"       </Style>\n");
+                       fprintf(fd,"      <Point>\n");
+                       fprintf(fd,"        <extrude>1</extrude>\n");
+                       fprintf(fd,"        <altitudeMode>relativeToGround</altitudeMode>\n");
+                       fprintf(fd,"        <coordinates>%f,%f,%f</coordinates>\n",(xmtr[x].lon<180.0?-xmtr[x].lon:360.0-xmtr[x].lon), xmtr[x].lat, xmtr[x].alt);
+                       fprintf(fd,"      </Point>\n");
+                       fprintf(fd,"     </Placemark>\n");
+               }
 
-       fprintf(stdout,"\nWriting \"%s\" (%ux%u pixmap image)... ",mapfile,width,height+30);
-       fflush(stdout);
+               fprintf(fd,"  </Folder>\n");
+               fprintf(fd,"</kml>\n");
 
-       for (y=0, lat=((double)max_north)-one_pixel; y<(int)height; y++, lat-=one_pixel)
-       {
-               minlat=(int)floor(lat);
+               fclose(fd);
+       }
+
+       fd=fopen(mapfile,"wb");
+
+       fprintf(fd,"P6\n%u %u\n255\n",width,(kml?height:height+30));
+       fprintf(stdout,"\nWriting \"%s\" (%ux%u pixmap image)... ",mapfile,width,(kml?height:height+30));
+       fflush(stdout);
 
-               for (x=0, lon=((double)max_west)-one_pixel; x<(int)width; x++, lon-=one_pixel)
+       for (y=0, lat=north; y<(int)height; y++, lat=north-(dpp*(double)y))
+       {
+               for (x=0, lon=max_west; x<(int)width; x++, lon=max_west-(dpp*(double)x))
                {
                        if (lon<0.0)
                                lon+=360.0;
 
-                       minlon=(int)floor(lon);
+                       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+                       {
+                               x0=(int)rint(ppd*(lat-(double)dem[indx].min_north));
+                               y0=mpi-(int)rint(ppd*(LonDiff((double)dem[indx].max_west,lon)));
 
-                       for (indx=0, found=0; indx<MAXSLOTS && found==0;)
-                               if (minlat==dem[indx].min_north && minlon==dem[indx].min_west)
+                               if (x0>=0 && x0<=mpi && y0>=0 && y0<=mpi)
                                        found=1;
                                else
                                        indx++;
+                       }
+
                        if (found)
                        {
-                               x0=(int)(1199.0*(lat-floor(lat)));
-                               y0=(int)(1199.0*(lon-floor(lon)));
-
                                mask=dem[indx].mask[x0][y0];
-                               loss=70+(10*(int)((mask&248)>>3));
+                               loss=(dem[indx].signal[x0][y0]);
                                cityorcounty=0;
 
+                               match=255;
+
+                               red=0;
+                               green=0;
+                               blue=0;
+
+                               if (loss<=region.level[0])
+                                       match=0;
+                               else
+                               {
+                                       for (z=1; (z<region.levels && match==255); z++)
+                                       {
+                                               if (loss>=region.level[z-1] && loss<region.level[z])
+                                                       match=z;
+                                       }
+                               }
+
+                               if (match<region.levels)
+                               {
+                                       red=region.color[match][0];
+                                       green=region.color[match][1];
+                                       blue=region.color[match][2];
+                               }
+
                                if (mask&2)
                                {
-                                       /* Text Labels - Black or Red */
+                                       /* Text Labels: Red or otherwise */
 
-                                       if ((mask&120) && (loss<=90))
-                                               fprintf(fd,"%c%c%c",0,0,0);
-                                       else
-                                               fprintf(fd,"%c%c%c",255,0,0);
+                                       if (red>=180 && green<=75 && blue<=75 && loss!=0)
+                                                fprintf(fd,"%c%c%c",255^red,255^green,255^blue);
+                                        else
+                                                fprintf(fd,"%c%c%c",255,0,0);
 
-                                       cityorcounty=1;
+                                        cityorcounty=1;
                                }
 
                                else if (mask&4)
@@ -3258,97 +4334,41 @@ void WritePPMLR(char *filename, unsigned char geo)
 
                                if (cityorcounty==0)
                                {
-                                       if (loss>maxdB)
-
-                                       { /* Display land or sea elevation */
-
-                                               if (dem[indx].data[x0][y0]==0)
-                                                       fprintf(fd,"%c%c%c",0,0,170);
+                                       if (loss==0 || (contour_threshold!=0 && loss>abs(contour_threshold)))
+                                       {
+                                               if (ngs)  /* No terrain */
+                                                       fprintf(fd,"%c%c%c",255,255,255);
                                                else
                                                {
-                                                       /* Elevation: Greyscale */
-                                                       output=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
-                                                       fprintf(fd,"%c%c%c",output,output,output);
+                                                       /* Display land or sea elevation */
+
+                                                       if (dem[indx].data[x0][y0]==0)
+                                                               fprintf(fd,"%c%c%c",0,0,170);
+                                                       else
+                                                       {
+                                                               terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                               fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                       }
                                                }
                                        }
 
-                                       else switch (loss)
+                                       else
                                        {
-                                               /* Plot signal loss in color */
-
-                                               case 80:
-                                               fprintf(fd,"%c%c%c",255,0,0);
-                                               break;
-
-                                               case 90:
-                                               fprintf(fd,"%c%c%c",255,128,0);
-                                               break;
-
-                                               case 100:
-                                               fprintf(fd,"%c%c%c",255,165,0);
-                                               break;
-
-                                               case 110:
-                                               fprintf(fd,"%c%c%c",255,206,0);
-                                               break;
-
-                                               case 120:
-                                               fprintf(fd,"%c%c%c",255,255,0);
-                                               break;
-
-                                               case 130:
-                                               fprintf(fd,"%c%c%c",184,255,0);
-                                               break;
-
-                                               case 140:
-                                               fprintf(fd,"%c%c%c",0,255,0);
-                                               break;
-
-                                               case 150:
-                                               fprintf(fd,"%c%c%c",0,208,0);
-                                               break;
-
-                                               case 160:
-                                               fprintf(fd,"%c%c%c",0,196,196);
-                                               break;
-
-                                               case 170:
-                                               fprintf(fd,"%c%c%c",0,148,255);
-                                               break;
-
-                                               case 180:
-                                               fprintf(fd,"%c%c%c",80,80,255);
-                                               break;
-
-                                               case 190:
-                                               fprintf(fd,"%c%c%c",0,38,255);
-                                               break;
-
-                                               case 200:
-                                               fprintf(fd,"%c%c%c",142,63,255);
-                                               break;
-
-                                               case 210:
-                                               fprintf(fd,"%c%c%c",196,54,255);
-                                               break;
-
-                                               case 220:
-                                               fprintf(fd,"%c%c%c",255,0,255);
-                                               break;
+                                               /* Plot path loss in color */
 
-                                               case 230:
-                                               fprintf(fd,"%c%c%c",255,194,204);
-                                               break;
-
-                                               default:
+                                               if (red!=0 || green!=0 || blue!=0)
+                                                       fprintf(fd,"%c%c%c",red,green,blue);
 
-                                               if (dem[indx].data[x0][y0]==0)
-                                                       fprintf(fd,"%c%c%c",0,0,170);
-                                               else
+                                               else  /* terrain / sea-level */
                                                {
-                                                       /* Elevation: Greyscale */
-                                                       output=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
-                                                       fprintf(fd,"%c%c%c",output,output,output);
+                                                       if (dem[indx].data[x0][y0]==0)
+                                                               fprintf(fd,"%c%c%c",0,0,170);
+                                                       else
+                                                       {
+                                                               /* Elevation: Greyscale */
+                                                               terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                               fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                       }
                                                }
                                        }
                                }
@@ -3364,106 +4384,72 @@ void WritePPMLR(char *filename, unsigned char geo)
                }
        }
 
-       /* Display legend along bottom of image */
+       if (kml==0 && geo==0)
+       {
+               /* Display legend along bottom of image
+                * if not generating .kml or .geo output.
+                */
 
-       x0=width/16;
+               colorwidth=(int)rint((float)width/(float)region.levels);
 
-       for (y0=0; y0<30; y0++)
-       {
-               for (indx=0; indx<16; indx++)
+               for (y0=0; y0<30; y0++)
                {
-                       for (x=0; x<x0; x++)
+                       for (x0=0; x0<(int)width; x0++)
                        {
-                               t=indx;  
-                               t2=indx+8;
-
-                               if (y0>=10 && y0<=18)
-                               {  
-                                       if (t2>9)
-                                       {
-                                               if (x>=11 && x<=17)     
-                                                       if (smallfont[t2/10][y0-10][x-11])
-                                                               t=255; 
-                                       }
-
-                                       if (x>=19 && x<=25)     
-                                               if (smallfont[t2%10][y0-10][x-19])
-                                                       t=255;
-                                       if (x>=27 && x<=33)
-                                               if (smallfont[0][y0-10][x-27])
-                                                       t=255; 
-                               }
-
-                               switch (t)
-                               {
-                                       case 0:
-                                       fprintf(fd,"%c%c%c",255,0,0);
-                                       break;
-
-                                       case 1:
-                                       fprintf(fd,"%c%c%c",255,128,0);
-                                       break;
-
-                                       case 2:
-                                       fprintf(fd,"%c%c%c",255,165,0);
-                                       break;
-
-                                       case 3:
-                                       fprintf(fd,"%c%c%c",255,206,0);
-                                       break;
-
-                                       case 4:
-                                       fprintf(fd,"%c%c%c",255,255,0);
-                                       break;
-
-                                       case 5:
-                                       fprintf(fd,"%c%c%c",184,255,0);
-                                       break;
+                               indx=x0/colorwidth;
+                               x=x0%colorwidth;
+                               level=region.level[indx];
 
-                                       case 6:
-                                       fprintf(fd,"%c%c%c",0,255,0);
-                                       break;
+                               hundreds=level/100;
 
-                                       case 7:
-                                       fprintf(fd,"%c%c%c",0,208,0);
-                                       break;
+                               if (hundreds>0)
+                                       level-=(hundreds*100);
 
-                                       case 8:
-                                       fprintf(fd,"%c%c%c",0,196,196);
-                                       break;
+                               tens=level/10;
 
-                                       case 9:
-                                       fprintf(fd,"%c%c%c",0,148,255);
-                                       break;
+                               if (tens>0)
+                                       level-=(tens*10);
 
-                                       case 10:
-                                       fprintf(fd,"%c%c%c",80,80,255);
-                                       break;
+                               units=level;
 
-                                       case 11:
-                                       fprintf(fd,"%c%c%c",0,38,255);
-                                       break;
+                               if (y0>=8 && y0<=23)
+                               {  
+                                       if (hundreds>0)
+                                       {
+                                               if (x>=11 && x<=18)     
+                                                       if (fontdata[16*(hundreds+'0')+(y0-8)]&(128>>(x-11)))
+                                                               indx=255; 
+                                       }
 
-                                       case 12:
-                                       fprintf(fd,"%c%c%c",142,63,255);
-                                       break;
+                                       if (tens>0 || hundreds>0)
+                                       {
+                                               if (x>=19 && x<=26)     
+                                                       if (fontdata[16*(tens+'0')+(y0-8)]&(128>>(x-19)))
+                                                               indx=255;
+                                       }
+                                       if (x>=27 && x<=34)
+                                               if (fontdata[16*(units+'0')+(y0-8)]&(128>>(x-27)))
+                                                       indx=255;
 
-                                       case 13:
-                                       fprintf(fd,"%c%c%c",196,54,255);
-                                       break;
+                                       if (x>=42 && x<=49)
+                                               if (fontdata[16*('d')+(y0-8)]&(128>>(x-42)))
+                                                       indx=255;
 
-                                       case 14:
-                                       fprintf(fd,"%c%c%c",255,0,255);
-                                       break;
+                                       if (x>=50 && x<=57)
+                                               if (fontdata[16*('B')+(y0-8)]&(128>>(x-50)))
+                                                       indx=255;
+                               }
 
-                                       case 255:
-                                       /* Black */
+                               if (indx>region.levels)
                                        fprintf(fd,"%c%c%c",0,0,0);
-                                       break;
+                               else
+                               {
+                                       red=region.color[indx][0];
+                                       green=region.color[indx][1];
+                                       blue=region.color[indx][2];
 
-                                       default:
-                                       fprintf(fd,"%c%c%c",255,194,204);
+                                       fprintf(fd,"%c%c%c",red,green,blue);
                                }
                        } 
                }
@@ -3474,215 +4460,874 @@ void WritePPMLR(char *filename, unsigned char geo)
        fflush(stdout);
 }
 
-void GraphTerrain(struct site source, struct site destination, char *name)
+void WritePPMSS(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites)
 {
-       /* This function invokes gnuplot to generate an appropriate
-          output file indicating the terrain profile between the source
-          and destination locations.  "filename" is the name assigned
-          to the output file generated by gnuplot.  The filename extension
-          is used to set gnuplot's terminal setting and output file type.
-          If no extension is found, .png is assumed.  */
+       /* This function generates a topographic map in Portable Pix Map
+          (PPM) format based on the signal strength values held in the
+          signal[][] array.  The image created is rotated counter-clockwise
+          90 degrees from its representation in dem[][] so that north
+          points up and east points right in the image generated. */
 
-       int     x, y, z;
-       char    filename[255], term[30], ext[15];
-       FILE    *fd=NULL;
+       char mapfile[255], geofile[255], kmlfile[255];
+       unsigned width, height, terrain, red, green, blue;
+       unsigned char found, mask, cityorcounty;
+       int indx, x, y, z=1, x0, y0, signal, level, hundreds,
+           tens, units, match, colorwidth;
+       double conversion, one_over_gamma, lat, lon,
+       north, south, east, west, minwest;
+       FILE *fd;
 
-       ReadPath(destination,source);
+       one_over_gamma=1.0/GAMMA;
+       conversion=255.0/pow((double)(max_elevation-min_elevation),one_over_gamma);
 
-       fd=fopen("profile.gp","wb");
+       width=(unsigned)(ippd*ReduceAngle(max_west-min_west));
+       height=(unsigned)(ippd*ReduceAngle(max_north-min_north));
 
-       for (x=0; x<path.length; x++)
-       {
-               if (metric)
-                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*path.elevation[x]);
+       LoadSignalColors(xmtr[0]);
 
-               else
-                       fprintf(fd,"%f\t%f\n",path.distance[x],path.elevation[x]);
+       if (filename[0]==0)
+       {
+               strncpy(filename, xmtr[0].filename,254);
+               filename[strlen(filename)-4]=0;  /* Remove .qth */
        }
 
-       fclose(fd);
+       y=strlen(filename);
 
-       if (name[0]==0)
+       if (y>4)
        {
-               /* Default filename and output file type */
-
-               strncpy(filename,"profile\0",8);
-               strncpy(term,"png\0",4);
-               strncpy(ext,"png\0",4);
+               if (filename[y-1]=='m' && filename[y-2]=='p' && filename[y-3]=='p' && filename[y-4]=='.')
+                       y-=4;
        }
 
-       else
+       for (x=0; x<y; x++)
        {
-               /* Grab extension and terminal type from "name" */
+               mapfile[x]=filename[x];
+               geofile[x]=filename[x];
+               kmlfile[x]=filename[x];
+       }
 
-               for (x=0; name[x]!='.' && name[x]!=0 && x<254; x++)
-                       filename[x]=name[x];
+       mapfile[x]='.';
+       geofile[x]='.';
+       kmlfile[x]='.';
+       mapfile[x+1]='p';
+       geofile[x+1]='g';
+       kmlfile[x+1]='k';
+       mapfile[x+2]='p';
+       geofile[x+2]='e';
+       kmlfile[x+2]='m';
+       mapfile[x+3]='m';
+       geofile[x+3]='o';
+       kmlfile[x+3]='l';
+       mapfile[x+4]=0;
+       geofile[x+4]=0;
+       kmlfile[x+4]=0;
 
-               if (name[x]=='.')
-               {
-                       for (y=0, z=x, x++; name[x]!=0 && x<254 && y<14; x++, y++)
-                       {
-                               term[y]=tolower(name[x]);
-                               ext[y]=term[y];
-                       }
+       minwest=((double)min_west)+dpp;
 
-                       ext[y]=0;
-                       term[y]=0;
-                       filename[z]=0;
-               }
+       if (minwest>360.0)
+               minwest-=360.0;
 
-               else
-               {       /* No extension -- Default is png */
+       north=(double)max_north-dpp;
 
-                       filename[x]=0;
-                       strncpy(term,"png\0",4);
-                       strncpy(ext,"png\0",4);
-               }
-       }
+       if (kml || geo)
+               south=(double)min_north;        /* No bottom legend */
+       else
+               south=(double)min_north-(30.0/ppd);     /* 30 pixels for bottom legend */
 
-       /* Either .ps or .postscript may be used
-          as an extension for postscript output. */
+       east=(minwest<180.0?-minwest:360.0-min_west);
+       west=(double)(max_west<180?-max_west:360-max_west);
 
-       if (strncmp(term,"postscript",10)==0)
-               strncpy(ext,"ps\0",3);
+       if (geo && kml==0)
+       {
+               fd=fopen(geofile,"wb");
 
-       else if (strncmp(ext,"ps",2)==0)
-               strncpy(term,"postscript enhanced color\0",26);
+               fprintf(fd,"FILENAME\t%s\n",mapfile);
+               fprintf(fd,"#\t\tX\tY\tLong\t\tLat\n");
+               fprintf(fd,"TIEPOINT\t0\t0\t%.3f\t\t%.3f\n",west,north);
 
-       fprintf(stdout,"Writing \"%s.%s\"...",filename,ext);
-       fflush(stdout);
+               fprintf(fd,"TIEPOINT\t%u\t%u\t%.3f\t\t%.3f\n",width-1,height-1,east,south);
+               fprintf(fd,"IMAGESIZE\t%u\t%u\n",width,height);
 
-       fd=fopen("splat.gp","w");
-       fprintf(fd,"set grid\n");
-       fprintf(fd,"set autoscale\n");
-       fprintf(fd,"set encoding iso_8859_1\n");
-       fprintf(fd,"set term %s\n",term);
-       fprintf(fd,"set title \"SPLAT! Terrain Profile Between %s and %s (%.2f%c Azimuth)\"\n",destination.name, source.name, Azimuth(destination,source),176);
+               fprintf(fd,"#\n# Auto Generated by %s v%s\n#\n",splat_name,splat_version);
 
-       if (metric)
-       {
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(source,destination));
-               fprintf(fd,"set ylabel \"Ground Elevation Above Sea Level (meters)\"\n");
+               fclose(fd);
+       }
 
+       if (kml && geo==0)
+       {
+               fd=fopen(kmlfile,"wb");
+
+               fprintf(fd,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               fprintf(fd,"<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+               fprintf(fd,"<!-- Generated by %s Version %s -->\n",splat_name,splat_version);
+               fprintf(fd,"  <Folder>\n");
+               fprintf(fd,"   <name>%s</name>\n",splat_name);
+               fprintf(fd,"     <description>%s Transmitter Coverage Overlay</description>\n",xmtr[0].name);
+               fprintf(fd,"       <GroundOverlay>\n");
+               fprintf(fd,"         <name>SPLAT! Signal Strength Overlay</name>\n");
+               fprintf(fd,"           <description>SPLAT! Coverage</description>\n");
+               fprintf(fd,"            <Icon>\n");
+               fprintf(fd,"              <href>%s</href>\n",mapfile);
+               fprintf(fd,"            </Icon>\n");
+               fprintf(fd,"            <opacity>128</opacity>\n");
+               fprintf(fd,"            <LatLonBox>\n");
+               fprintf(fd,"               <north>%.5f</north>\n",north);
+               fprintf(fd,"               <south>%.5f</south>\n",south);
+               fprintf(fd,"               <east>%.5f</east>\n",east);
+               fprintf(fd,"               <west>%.5f</west>\n",west);
+               fprintf(fd,"               <rotation>0.0</rotation>\n");
+               fprintf(fd,"            </LatLonBox>\n");
+               fprintf(fd,"       </GroundOverlay>\n");
 
-       }
+               for (x=0; x<txsites; x++)
+               {
+                       fprintf(fd,"     <Placemark>\n");
+                       fprintf(fd,"       <name>%s</name>\n",xmtr[x].name);
+                       fprintf(fd,"       <visibility>1</visibility>\n");
+                       fprintf(fd,"       <Style>\n");
+                       fprintf(fd,"       <IconStyle>\n");
+                       fprintf(fd,"        <Icon>\n");
+                       fprintf(fd,"          <href>root://icons/palette-5.png</href>\n");
+                       fprintf(fd,"          <x>224</x>\n");
+                       fprintf(fd,"          <y>224</y>\n");
+                       fprintf(fd,"          <w>32</w>\n");
+                       fprintf(fd,"          <h>32</h>\n");
+                       fprintf(fd,"        </Icon>\n");
+                       fprintf(fd,"       </IconStyle>\n");
+                       fprintf(fd,"       </Style>\n");
+                       fprintf(fd,"      <Point>\n");
+                       fprintf(fd,"        <extrude>1</extrude>\n");
+                       fprintf(fd,"        <altitudeMode>relativeToGround</altitudeMode>\n");
+                       fprintf(fd,"        <coordinates>%f,%f,%f</coordinates>\n",(xmtr[x].lon<180.0?-xmtr[x].lon:360.0-xmtr[x].lon), xmtr[x].lat, xmtr[x].alt);
+                       fprintf(fd,"      </Point>\n");
+                       fprintf(fd,"     </Placemark>\n");
+               }
 
-       else
-       {
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(source,destination));
-               fprintf(fd,"set ylabel \"Ground Elevation Above Sea Level (feet)\"\n");
+               fprintf(fd,"  </Folder>\n");
+               fprintf(fd,"</kml>\n");
+
+               fclose(fd);
        }
 
-       fprintf(fd,"set output \"%s.%s\"\n",filename,ext);
-       fprintf(fd,"plot \"profile.gp\" title \"\" with lines\n");
-       fclose(fd);
-                       
-       x=system("gnuplot splat.gp");
+       fd=fopen(mapfile,"wb");
 
-       if (x!=-1)
+       fprintf(fd,"P6\n%u %u\n255\n",width,(kml?height:height+30));
+       fprintf(stdout,"\nWriting \"%s\" (%ux%u pixmap image)... ",mapfile,width,(kml?height:height+30));
+       fflush(stdout);
+
+       for (y=0, lat=north; y<(int)height; y++, lat=north-(dpp*(double)y))
        {
-               unlink("splat.gp");
-               unlink("profile.gp");
-               fprintf(stdout," Done!\n");
-               fflush(stdout);
-       }
+               for (x=0, lon=max_west; x<(int)width; x++, lon=max_west-(dpp*(double)x))
+               {
+                       if (lon<0.0)
+                               lon+=360.0;
 
-       else
-               fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
-}
+                       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+                       {
+                               x0=(int)rint(ppd*(lat-(double)dem[indx].min_north));
+                               y0=mpi-(int)rint(ppd*(LonDiff((double)dem[indx].max_west,lon)));
 
-void GraphElevation(struct site source, struct site destination, char *name)
-{
-       /* This function invokes gnuplot to generate an appropriate
-          output file indicating the terrain profile between the source
-          and destination locations.  "filename" is the name assigned
-          to the output file generated by gnuplot.  The filename extension
-          is used to set gnuplot's terminal setting and output file type.
-          If no extension is found, .png is assumed. */
+                               if (x0>=0 && x0<=mpi && y0>=0 && y0<=mpi)
+                                       found=1;
+                               else
+                                       indx++;
+                       }
 
-       int     x, y, z;
-       char    filename[255], term[30], ext[15];
-       double  angle, refangle, maxangle=-90.0;
-       struct  site remote;
-       FILE    *fd=NULL, *fd2=NULL;
+                       if (found)
+                       {
+                               mask=dem[indx].mask[x0][y0];
+                               signal=(dem[indx].signal[x0][y0])-100;
+                               cityorcounty=0;
 
-       ReadPath(destination,source);  /* destination=RX, source=TX */
-       refangle=ElevationAngle(destination,source);
+                               match=255;
 
-       fd=fopen("profile.gp","wb");
-       fd2=fopen("reference.gp","wb");
+                               red=0;
+                               green=0;
+                               blue=0;
 
-       for (x=1; x<path.length-1; x++)
-       {
-               remote.lat=path.lat[x];
-               remote.lon=path.lon[x];
-               remote.alt=0.0;
-               angle=ElevationAngle(destination,remote);
+                               if (signal>=region.level[0])
+                                       match=0;
+                               else
+                               {
+                                       for (z=1; (z<region.levels && match==255); z++)
+                                       {
+                                               if (signal<region.level[z-1] && signal>=region.level[z])
+                                                       match=z;
+                                       }
+                               }
 
-               if (metric)
-               {
-                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],angle);
-                       fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[x],refangle);
-               }
+                               if (match<region.levels)
+                               {
+                                       red=region.color[match][0];
+                                       green=region.color[match][1];
+                                       blue=region.color[match][2];
+                               }
 
-               else
-               {
-                       fprintf(fd,"%f\t%f\n",path.distance[x],angle);
-                       fprintf(fd2,"%f\t%f\n",path.distance[x],refangle);
-               }
+                               if (mask&2) 
+                               {
+                                       /* Text Labels: Red or otherwise */
 
-               if (angle>maxangle)
-                       maxangle=angle;
+                                       if (red>=180 && green<=75 && blue<=75)
+                                               fprintf(fd,"%c%c%c",255^red,255^green,255^blue);
+                                       else
+                                               fprintf(fd,"%c%c%c",255,0,0);
+
+                                       cityorcounty=1;
+                               }
+
+                               else if (mask&4)
+                               {
+                                       /* County Boundaries: Black */
+
+                                       fprintf(fd,"%c%c%c",0,0,0);
+
+                                       cityorcounty=1;
+                               }
+
+                               if (cityorcounty==0)
+                               {
+                                       if (contour_threshold!=0 && signal<contour_threshold)
+                                       {
+                                               if (ngs)
+                                                       fprintf(fd,"%c%c%c",255,255,255);
+                                               else
+                                               {
+                                                       /* Display land or sea elevation */
+
+                                                       if (dem[indx].data[x0][y0]==0)
+                                                               fprintf(fd,"%c%c%c",0,0,170);
+                                                       else
+                                                       {
+                                                               terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                               fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                       }
+                                               }
+                                       }
+
+                                       else
+                                       {
+                                               /* Plot field strength regions in color */
+
+                                               if (red!=0 || green!=0 || blue!=0)
+                                                       fprintf(fd,"%c%c%c",red,green,blue);
+
+                                               else  /* terrain / sea-level */
+                                               {
+                                                       if (ngs)
+                                                               fprintf(fd,"%c%c%c",255,255,255);
+                                                       else
+                                                       {
+                                                               if (dem[indx].data[x0][y0]==0)
+                                                                       fprintf(fd,"%c%c%c",0,0,170);
+                                                               else
+                                                               {
+                                                                       /* Elevation: Greyscale */
+                                                                       terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                                       fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       else
+                       {
+                               /* We should never get here, but if */
+                               /* we do, display the region as black */
+
+                               fprintf(fd,"%c%c%c",0,0,0);
+                       }
+               }
        }
 
-       if (metric)
+       if (kml==0 && geo==0)
        {
-               fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],refangle);
-               fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],refangle);
+               /* Display legend along bottom of image
+                * if not generating .kml or .geo output.
+                */
+
+               colorwidth=(int)rint((float)width/(float)region.levels);
+
+               for (y0=0; y0<30; y0++)
+               {
+                       for (x0=0; x0<(int)width; x0++)
+                       {
+                               indx=x0/colorwidth;
+                               x=x0%colorwidth;
+                               level=region.level[indx];
+
+                               hundreds=level/100;
+
+                               if (hundreds>0)
+                                       level-=(hundreds*100);
+
+                               tens=level/10;
+
+                               if (tens>0)
+                                       level-=(tens*10);
+
+                               units=level;
+
+                               if (y0>=8 && y0<=23)
+                               {  
+                                       if (hundreds>0)
+                                       {
+                                               if (x>=5 && x<=12)     
+                                                       if (fontdata[16*(hundreds+'0')+(y0-8)]&(128>>(x-5)))
+                                                               indx=255; 
+                                       }
+
+                                       if (tens>0 || hundreds>0)
+                                       {
+                                               if (x>=13 && x<=20)     
+                                                       if (fontdata[16*(tens+'0')+(y0-8)]&(128>>(x-13)))
+                                                               indx=255;
+                                       }
+                                       if (x>=21 && x<=28)
+                                               if (fontdata[16*(units+'0')+(y0-8)]&(128>>(x-21)))
+                                                       indx=255;
+
+                                       if (x>=36 && x<=43)
+                                               if (fontdata[16*('d')+(y0-8)]&(128>>(x-36)))
+                                                       indx=255;
+
+                                       if (x>=44 && x<=51)
+                                               if (fontdata[16*('B')+(y0-8)]&(128>>(x-44)))
+                                                       indx=255;
+
+                                       if (x>=52 && x<=59)
+                                               if (fontdata[16*(230)+(y0-8)]&(128>>(x-52)))
+                                                       indx=255;
+
+                                       if (x>=60 && x<=67)
+                                               if (fontdata[16*('V')+(y0-8)]&(128>>(x-60)))
+                                                       indx=255;
+
+                                       if (x>=68 && x<=75)
+                                               if (fontdata[16*('/')+(y0-8)]&(128>>(x-68)))
+                                                       indx=255;
+
+                                       if (x>=76 && x<=83)
+                                               if (fontdata[16*('m')+(y0-8)]&(128>>(x-76)))
+                                                       indx=255;
+                               }
+
+                               if (indx>region.levels)
+                                       fprintf(fd,"%c%c%c",0,0,0);
+                               else
+                               {
+                                       red=region.color[indx][0];
+                                       green=region.color[indx][1];
+                                       blue=region.color[indx][2];
+
+                                       fprintf(fd,"%c%c%c",red,green,blue);
+                               }
+                       } 
+               }
+       }
+
+       fclose(fd);
+       fprintf(stdout,"Done!\n");
+       fflush(stdout);
+}
+
+void WritePPMDBM(char *filename, unsigned char geo, unsigned char kml, unsigned char ngs, struct site *xmtr, unsigned char txsites)
+{
+       /* This function generates a topographic map in Portable Pix Map
+          (PPM) format based on the signal power level values held in the
+          signal[][] array.  The image created is rotated counter-clockwise
+          90 degrees from its representation in dem[][] so that north
+          points up and east points right in the image generated. */
+
+       char mapfile[255], geofile[255], kmlfile[255];
+       unsigned width, height, terrain, red, green, blue;
+       unsigned char found, mask, cityorcounty;
+       int indx, x, y, z=1, x0, y0, dBm, level, hundreds,
+           tens, units, match, colorwidth;
+       double conversion, one_over_gamma, lat, lon,
+       north, south, east, west, minwest;
+       FILE *fd;
+
+       one_over_gamma=1.0/GAMMA;
+       conversion=255.0/pow((double)(max_elevation-min_elevation),one_over_gamma);
+
+       width=(unsigned)(ippd*ReduceAngle(max_west-min_west));
+       height=(unsigned)(ippd*ReduceAngle(max_north-min_north));
+
+       LoadDBMColors(xmtr[0]);
+
+       if (filename[0]==0)
+       {
+               strncpy(filename, xmtr[0].filename,254);
+               filename[strlen(filename)-4]=0;  /* Remove .qth */
        }
 
+       y=strlen(filename);
+
+       if (y>4)
+       {
+               if (filename[y-1]=='m' && filename[y-2]=='p' && filename[y-3]=='p' && filename[y-4]=='.')
+                       y-=4;
+       }
+
+       for (x=0; x<y; x++)
+       {
+               mapfile[x]=filename[x];
+               geofile[x]=filename[x];
+               kmlfile[x]=filename[x];
+       }
+
+       mapfile[x]='.';
+       geofile[x]='.';
+       kmlfile[x]='.';
+       mapfile[x+1]='p';
+       geofile[x+1]='g';
+       kmlfile[x+1]='k';
+       mapfile[x+2]='p';
+       geofile[x+2]='e';
+       kmlfile[x+2]='m';
+       mapfile[x+3]='m';
+       geofile[x+3]='o';
+       kmlfile[x+3]='l';
+       mapfile[x+4]=0;
+       geofile[x+4]=0;
+       kmlfile[x+4]=0;
+
+       minwest=((double)min_west)+dpp;
+
+       if (minwest>360.0)
+               minwest-=360.0;
+
+       north=(double)max_north-dpp;
+
+       if (kml || geo)
+               south=(double)min_north;        /* No bottom legend */
        else
+               south=(double)min_north-(30.0/ppd);     /* 30 pixels for bottom legend */
+
+       east=(minwest<180.0?-minwest:360.0-min_west);
+       west=(double)(max_west<180?-max_west:360-max_west);
+
+       if (geo && kml==0)
        {
-               fprintf(fd,"%f\t%f\n",path.distance[path.length-1],refangle);
-               fprintf(fd2,"%f\t%f\n",path.distance[path.length-1],refangle);
+               fd=fopen(geofile,"wb");
+
+               fprintf(fd,"FILENAME\t%s\n",mapfile);
+               fprintf(fd,"#\t\tX\tY\tLong\t\tLat\n");
+               fprintf(fd,"TIEPOINT\t0\t0\t%.3f\t\t%.3f\n",west,north);
+
+               fprintf(fd,"TIEPOINT\t%u\t%u\t%.3f\t\t%.3f\n",width-1,height-1,east,south);
+               fprintf(fd,"IMAGESIZE\t%u\t%u\n",width,height);
+
+               fprintf(fd,"#\n# Auto Generated by %s v%s\n#\n",splat_name,splat_version);
+
+               fclose(fd);
+       }
+
+       if (kml && geo==0)
+       {
+               fd=fopen(kmlfile,"wb");
+
+               fprintf(fd,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               fprintf(fd,"<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+               fprintf(fd,"<!-- Generated by %s Version %s -->\n",splat_name,splat_version);
+               fprintf(fd,"  <Folder>\n");
+               fprintf(fd,"   <name>%s</name>\n",splat_name);
+               fprintf(fd,"     <description>%s Transmitter Coverage Overlay</description>\n",xmtr[0].name);
+               fprintf(fd,"       <GroundOverlay>\n");
+               fprintf(fd,"         <name>SPLAT! Signal Power Level Overlay</name>\n");
+               fprintf(fd,"           <description>SPLAT! Coverage</description>\n");
+               fprintf(fd,"            <Icon>\n");
+               fprintf(fd,"              <href>%s</href>\n",mapfile);
+               fprintf(fd,"            </Icon>\n");
+               fprintf(fd,"            <opacity>128</opacity>\n");
+               fprintf(fd,"            <LatLonBox>\n");
+               fprintf(fd,"               <north>%.5f</north>\n",north);
+               fprintf(fd,"               <south>%.5f</south>\n",south);
+               fprintf(fd,"               <east>%.5f</east>\n",east);
+               fprintf(fd,"               <west>%.5f</west>\n",west);
+               fprintf(fd,"               <rotation>0.0</rotation>\n");
+               fprintf(fd,"            </LatLonBox>\n");
+               fprintf(fd,"       </GroundOverlay>\n");
+
+               for (x=0; x<txsites; x++)
+               {
+                       fprintf(fd,"     <Placemark>\n");
+                       fprintf(fd,"       <name>%s</name>\n",xmtr[x].name);
+                       fprintf(fd,"       <visibility>1</visibility>\n");
+                       fprintf(fd,"       <Style>\n");
+                       fprintf(fd,"       <IconStyle>\n");
+                       fprintf(fd,"        <Icon>\n");
+                       fprintf(fd,"          <href>root://icons/palette-5.png</href>\n");
+                       fprintf(fd,"          <x>224</x>\n");
+                       fprintf(fd,"          <y>224</y>\n");
+                       fprintf(fd,"          <w>32</w>\n");
+                       fprintf(fd,"          <h>32</h>\n");
+                       fprintf(fd,"        </Icon>\n");
+                       fprintf(fd,"       </IconStyle>\n");
+                       fprintf(fd,"       </Style>\n");
+                       fprintf(fd,"      <Point>\n");
+                       fprintf(fd,"        <extrude>1</extrude>\n");
+                       fprintf(fd,"        <altitudeMode>relativeToGround</altitudeMode>\n");
+                       fprintf(fd,"        <coordinates>%f,%f,%f</coordinates>\n",(xmtr[x].lon<180.0?-xmtr[x].lon:360.0-xmtr[x].lon), xmtr[x].lat, xmtr[x].alt);
+                       fprintf(fd,"      </Point>\n");
+                       fprintf(fd,"     </Placemark>\n");
+               }
+
+               fprintf(fd,"  </Folder>\n");
+               fprintf(fd,"</kml>\n");
+
+               fclose(fd);
+       }
+
+       fd=fopen(mapfile,"wb");
+
+       fprintf(fd,"P6\n%u %u\n255\n",width,(kml?height:height+30));
+       fprintf(stdout,"\nWriting \"%s\" (%ux%u pixmap image)... ",mapfile,width,(kml?height:height+30));
+       fflush(stdout);
+
+       for (y=0, lat=north; y<(int)height; y++, lat=north-(dpp*(double)y))
+       {
+               for (x=0, lon=max_west; x<(int)width; x++, lon=max_west-(dpp*(double)x))
+               {
+                       if (lon<0.0)
+                               lon+=360.0;
+
+                       for (indx=0, found=0; indx<MAXPAGES && found==0;)
+                       {
+                               x0=(int)rint(ppd*(lat-(double)dem[indx].min_north));
+                               y0=mpi-(int)rint(ppd*(LonDiff((double)dem[indx].max_west,lon)));
+
+                               if (x0>=0 && x0<=mpi && y0>=0 && y0<=mpi)
+                                       found=1;
+                               else
+                                       indx++;
+                       }
+
+                       if (found)
+                       {
+                               mask=dem[indx].mask[x0][y0];
+                               dBm=(dem[indx].signal[x0][y0])-200;
+                               cityorcounty=0;
+
+                               match=255;
+
+                               red=0;
+                               green=0;
+                               blue=0;
+
+                               if (dBm>=region.level[0])
+                                       match=0;
+                               else
+                               {
+                                       for (z=1; (z<region.levels && match==255); z++)
+                                       {
+                                               if (dBm<region.level[z-1] && dBm>=region.level[z])
+                                                       match=z;
+                                       }
+                               }
+
+                               if (match<region.levels)
+                               {
+                                       red=region.color[match][0];
+                                       green=region.color[match][1];
+                                       blue=region.color[match][2];
+                               }
+
+                               if (mask&2) 
+                               {
+                                       /* Text Labels: Red or otherwise */
+
+                                       if (red>=180 && green<=75 && blue<=75 && dBm!=0)
+                                               fprintf(fd,"%c%c%c",255^red,255^green,255^blue);
+                                       else
+                                               fprintf(fd,"%c%c%c",255,0,0);
+
+                                       cityorcounty=1;
+                               }
+
+                               else if (mask&4)
+                               {
+                                       /* County Boundaries: Black */
+
+                                       fprintf(fd,"%c%c%c",0,0,0);
+
+                                       cityorcounty=1;
+                               }
+
+                               if (cityorcounty==0)
+                               {
+                                       if (contour_threshold!=0 && dBm<contour_threshold)
+                                       {
+                                               if (ngs) /* No terrain */
+                                                       fprintf(fd,"%c%c%c",255,255,255);
+                                               else
+                                               {
+                                                       /* Display land or sea elevation */
+
+                                                       if (dem[indx].data[x0][y0]==0)
+                                                               fprintf(fd,"%c%c%c",0,0,170);
+                                                       else
+                                                       {
+                                                               terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                               fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                       }
+                                               }
+                                       }
+
+                                       else
+                                       {
+                                               /* Plot signal power level regions in color */
+
+                                               if (red!=0 || green!=0 || blue!=0)
+                                                       fprintf(fd,"%c%c%c",red,green,blue);
+
+                                               else  /* terrain / sea-level */
+                                               {
+                                                       if (ngs)
+                                                               fprintf(fd,"%c%c%c",255,255,255);
+                                                       else
+                                                       {
+                                                               if (dem[indx].data[x0][y0]==0)
+                                                                       fprintf(fd,"%c%c%c",0,0,170);
+                                                               else
+                                                               {
+                                                                       /* Elevation: Greyscale */
+                                                                       terrain=(unsigned)(0.5+pow((double)(dem[indx].data[x0][y0]-min_elevation),one_over_gamma)*conversion);
+                                                                       fprintf(fd,"%c%c%c",terrain,terrain,terrain);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       else
+                       {
+                               /* We should never get here, but if */
+                               /* we do, display the region as black */
+
+                               fprintf(fd,"%c%c%c",0,0,0);
+                       }
+               }
+       }
+
+       if (kml==0 && geo==0)
+       {
+               /* Display legend along bottom of image
+                  if not generating .kml or .geo output. */
+
+               colorwidth=(int)rint((float)width/(float)region.levels);
+
+               for (y0=0; y0<30; y0++)
+               {
+                       for (x0=0; x0<(int)width; x0++)
+                       {
+                               indx=x0/colorwidth;
+                               x=x0%colorwidth;
+
+                               level=abs(region.level[indx]);
+
+                               hundreds=level/100;
+
+                               if (hundreds>0)
+                                       level-=(hundreds*100);
+
+                               tens=level/10;
+
+                               if (tens>0)
+                                       level-=(tens*10);
+
+                               units=level;
+
+                               if (y0>=8 && y0<=23)
+                               {
+                                       if (hundreds>0)
+                                       {
+                                               if (region.level[indx]<0)
+                                               {
+                                                       if (x>=5 && x<=12)
+                                                               if (fontdata[16*('-')+(y0-8)]&(128>>(x-5)))
+                                                                       indx=255;
+                                               }
+
+                                               else
+                                               {       
+                                                       if (x>=5 && x<=12)
+                                                               if (fontdata[16*('+')+(y0-8)]&(128>>(x-5)))
+                                                                       indx=255;
+                                               }
+
+                                               if (x>=13 && x<=20)     
+                                                       if (fontdata[16*(hundreds+'0')+(y0-8)]&(128>>(x-13)))
+                                                               indx=255; 
+                                       }
+
+                                       if (tens>0 || hundreds>0)
+                                       {
+                                               if (hundreds==0)
+                                               {
+                                                       if (region.level[indx]<0)
+                                                       {
+                                                               if (x>=13 && x<=20)
+                                                                       if (fontdata[16*('-')+(y0-8)]&(128>>(x-13)))
+                                                                               indx=255;
+                                                       }
+
+                                                       else
+                                                       {
+                                                               if (x>=13 && x<=20)
+                                                                       if (fontdata[16*('+')+(y0-8)]&(128>>(x-13)))
+                                                                               indx=255;
+                                                       }
+                                               }
+                                               
+                                               if (x>=21 && x<=28)     
+                                                       if (fontdata[16*(tens+'0')+(y0-8)]&(128>>(x-21)))
+                                                               indx=255;
+                                       }
+
+                                       if (hundreds==0 && tens==0)
+                                       {
+                                               if (region.level[indx]<0)
+                                               {
+                                                       if (x>=21 && x<=28)
+                                                               if (fontdata[16*('-')+(y0-8)]&(128>>(x-21)))
+                                                                       indx=255;
+                                               }
+
+                                               else
+                                               {
+                                                       if (x>=21 && x<=28)
+                                                               if (fontdata[16*('+')+(y0-8)]&(128>>(x-21)))
+                                                                       indx=255;
+                                               }
+                                       }
+
+                                       if (x>=29 && x<=36)
+                                               if (fontdata[16*(units+'0')+(y0-8)]&(128>>(x-29)))
+                                                       indx=255;
+
+                                       if (x>=37 && x<=44)
+                                               if (fontdata[16*('d')+(y0-8)]&(128>>(x-37)))
+                                                       indx=255;
+
+                                       if (x>=45 && x<=52)
+                                               if (fontdata[16*('B')+(y0-8)]&(128>>(x-45)))
+                                                       indx=255;
+
+                                       if (x>=53 && x<=60)
+                                               if (fontdata[16*('m')+(y0-8)]&(128>>(x-53)))
+                                                       indx=255;
+                               }
+
+                               if (indx>region.levels)
+                                       fprintf(fd,"%c%c%c",0,0,0);
+                               else
+                               {
+                                       red=region.color[indx][0];
+                                       green=region.color[indx][1];
+                                       blue=region.color[indx][2];
+
+                                       fprintf(fd,"%c%c%c",red,green,blue);
+                               }
+                       } 
+               }
        }
 
        fclose(fd);
-       fclose(fd2);
+       fprintf(stdout,"Done!\n");
+       fflush(stdout);
+}
 
-       if (name[0]==0)
+void GraphTerrain(struct site source, struct site destination, char *name)
+{
+       /* This function invokes gnuplot to generate an appropriate
+          output file indicating the terrain profile between the source
+          and destination locations when the -p command line option
+          is used.  "basename" is the name assigned to the output
+          file generated by gnuplot.  The filename extension is used
+          to set gnuplot's terminal setting and output file type.
+          If no extension is found, .png is assumed.  */
+
+       int     x, y, z;
+       char    basename[255], term[30], ext[15];
+       double  minheight=100000.0, maxheight=-100000.0;
+       FILE    *fd=NULL, *fd1=NULL;
+
+       ReadPath(destination,source);
+
+       fd=fopen("profile.gp","wb");
+
+       if (clutter>0.0)
+               fd1=fopen("clutter.gp","wb");
+
+       for (x=0; x<path.length; x++)
+       {
+               if ((path.elevation[x]+clutter)>maxheight)
+                       maxheight=path.elevation[x]+clutter;
+
+               if (path.elevation[x]<minheight)
+                       minheight=path.elevation[x];
+
+               if (metric)
+               {
+                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*path.elevation[x]);
+
+                       if (fd1!=NULL && x>0 && x<path.length-2)
+                               fprintf(fd1,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*(path.elevation[x]==0.0?path.elevation[x]:(path.elevation[x]+clutter)));
+               }
+
+               else
+               {
+                       fprintf(fd,"%f\t%f\n",path.distance[x],path.elevation[x]);
+
+                       if (fd1!=NULL && x>0 && x<path.length-2)
+                               fprintf(fd1,"%f\t%f\n",path.distance[x],(path.elevation[x]==0.0?path.elevation[x]:(path.elevation[x]+clutter)));
+               }
+       }
+
+       fclose(fd);
+
+       if (fd1!=NULL)
+               fclose(fd1);
+
+       if (name[0]=='.')
        {
                /* Default filename and output file type */
 
-               strncpy(filename,"profile\0",8);
+               strncpy(basename,"profile\0",8);
                strncpy(term,"png\0",4);
                strncpy(ext,"png\0",4);
        }
 
        else
        {
-               /* Grab extension and terminal type from "name" */
+               /* Extract extension and terminal type from "name" */
 
-               for (x=0; name[x]!='.' && name[x]!=0 && x<254; x++)
-                       filename[x]=name[x];
+               ext[0]=0;
+               y=strlen(name);
+               strncpy(basename,name,254);
 
-               if (name[x]=='.')
+               for (x=y-1; x>0 && name[x]!='.'; x--);
+
+               if (x>0)  /* Extension found */
                {
-                       for (y=0, z=x, x++; name[x]!=0 && x<254 && y<14; x++, y++)
+                       for (z=x+1; z<=y && (z-(x+1))<10; z++)
                        {
-                               term[y]=tolower(name[x]);
-                               ext[y]=term[y];
+                               ext[z-(x+1)]=tolower(name[z]);
+                               term[z-(x+1)]=name[z];
                        }
 
-                       ext[y]=0;
-                       term[y]=0;
-                       filename[z]=0;
+                       ext[z-(x+1)]=0;  /* Ensure an ending 0 */
+                       term[z-(x+1)]=0;
+                       basename[x]=0;
                }
 
-               else
-               {       /* No extension -- Default is png */
-
-                       filename[x]=0;
+               if (ext[0]==0)  /* No extension -- Default is png */
+               {
                        strncpy(term,"png\0",4);
                        strncpy(ext,"png\0",4);
                }
@@ -3695,28 +5340,41 @@ void GraphElevation(struct site source, struct site destination, char *name)
                strncpy(ext,"ps\0",3);
 
        else if (strncmp(ext,"ps",2)==0)
-               strncpy(term,"postscript enhanced color\0",26);
+                       strncpy(term,"postscript enhanced color\0",26);
 
-       fprintf(stdout,"Writing \"%s.%s\"...",filename,ext);
-       fflush(stdout);
+       minheight-=(0.01*maxheight);
 
        fd=fopen("splat.gp","w");
-
        fprintf(fd,"set grid\n");
-       fprintf(fd,"set yrange [%2.3f to %2.3f]\n", (-fabs(refangle)-0.25), maxangle+0.25);
+       fprintf(fd,"set yrange [%2.3f to %2.3f]\n", metric?minheight*METERS_PER_FOOT:minheight, metric?maxheight*METERS_PER_FOOT:maxheight);
        fprintf(fd,"set encoding iso_8859_1\n");
        fprintf(fd,"set term %s\n",term);
-       fprintf(fd,"set title \"SPLAT! Elevation Profile Between %s and %s (%.2f%c azimuth)\"\n",destination.name,source.name,Azimuth(destination,source),176);
+       fprintf(fd,"set title \"%s Terrain Profile Between %s and %s (%.2f%c Azimuth)\"\n",splat_name,destination.name, source.name, Azimuth(destination,source),176);
 
        if (metric)
+       {
                fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(source,destination));
+               fprintf(fd,"set ylabel \"Ground Elevation Above Sea Level (meters)\"\n");
+       }
+
        else
+       {
                fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(source,destination));
+               fprintf(fd,"set ylabel \"Ground Elevation Above Sea Level (feet)\"\n");
+       }
 
+       fprintf(fd,"set output \"%s.%s\"\n",basename,ext);
 
-       fprintf(fd,"set ylabel \"Elevation Angle Along LOS Path Between %s and %s (degrees)\"\n",destination.name,source.name);
-       fprintf(fd,"set output \"%s.%s\"\n",filename,ext);
-       fprintf(fd,"plot \"profile.gp\" title \"Real Earth Profile\" with lines, \"reference.gp\" title \"Line of Sight Path (%.2f%c elevation)\" with lines\n",refangle,176);
+       if (clutter>0.0)
+       {
+               if (metric)
+                       fprintf(fd,"plot \"profile.gp\" title \"Terrain Profile\" with lines, \"clutter.gp\" title \"Clutter Profile (%.2f meters)\" with lines\n",clutter*METERS_PER_FOOT);
+               else
+                       fprintf(fd,"plot \"profile.gp\" title \"Terrain Profile\" with lines, \"clutter.gp\" title \"Clutter Profile (%.2f feet)\" with lines\n",clutter);
+       }
+
+       else
+               fprintf(fd,"plot \"profile.gp\" title \"\" with lines\n");
 
        fclose(fd);
                        
@@ -3724,11 +5382,13 @@ void GraphElevation(struct site source, struct site destination, char *name)
 
        if (x!=-1)
        {
-               unlink("splat.gp");
-               unlink("profile.gp");
-               unlink("reference.gp"); 
+               if (gpsav==0)
+               {       
+                       unlink("splat.gp");
+                       unlink("profile.gp");
+               }
 
-               fprintf(stdout," Done!\n");
+               fprintf(stdout,"Terrain plot written to: \"%s.%s\"\n",basename,ext);
                fflush(stdout);
        }
 
@@ -3736,235 +5396,137 @@ void GraphElevation(struct site source, struct site destination, char *name)
                fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
 }
 
-void GraphHeight(struct site source, struct site destination, char *name, double f, unsigned char n)
+void GraphElevation(struct site source, struct site destination, char *name)
 {
        /* This function invokes gnuplot to generate an appropriate
-          output file indicating the terrain profile between the source
-          and destination locations referenced to the line-of-sight path
-          between the receive and transmit sites.  "filename" is the name
-          assigned to the output file generated by gnuplot.  The filename
-          extension is used to set gnuplot's terminal setting and output
-          file type.  If no extension is found, .png is assumed. */
+          output file indicating the terrain elevation profile between
+          the source and destination locations when the -e command line
+          option is used.  "basename" is the name assigned to the output
+          file generated by gnuplot.  The filename extension is used
+          to set gnuplot's terminal setting and output file type.
+          If no extension is found, .png is assumed.  */
 
        int     x, y, z;
-       char    filename[255], term[30], ext[15];
-       double  a, b, c, height=0.0, refangle, cangle, maxheight=-100000.0,
-               minheight=100000.0, lambda=0.0, f_zone=0.0, fpt6_zone=0.0,
-               nm=0.0, nb=0.0, ed=0.0, es=0.0, r=0.0, d=0.0, d1=0.0,
-               terrain, azimuth, distance, dheight=0.0, minterrain=100000.0,
-               minearth=100000.0, miny, maxy, min2y, max2y;
-       struct  site remote;
-       FILE    *fd=NULL, *fd2=NULL, *fd3=NULL, *fd4=NULL, *fd5=NULL;
+       char    basename[255], term[30], ext[15];
+       double  angle, clutter_angle=0.0, refangle, maxangle=-90.0,
+               minangle=90.0, distance;
+       struct  site remote, remote2;
+       FILE    *fd=NULL, *fd1=NULL, *fd2=NULL;
 
        ReadPath(destination,source);  /* destination=RX, source=TX */
-       azimuth=Azimuth(destination,source);
-       distance=Distance(destination,source);
        refangle=ElevationAngle(destination,source);
-       b=GetElevation(destination)+destination.alt+earthradius;
-
-       /* Wavelength and path distance (great circle) in feet. */
+       distance=Distance(source,destination);
 
-       if (f)
-       {
-               lambda=9.8425e8/(f*1e6);
-               d=5280.0*path.distance[path.length-1];
-       }
+       fd=fopen("profile.gp","wb");
 
-       if (n)
-       {
-               ed=GetElevation(destination);
-               es=GetElevation(source);
-               nb=-destination.alt-ed;
-               nm=(-source.alt-es-nb)/(path.distance[path.length-1]);
-       }
+       if (clutter>0.0)
+               fd1=fopen("clutter.gp","wb");
 
-       fd=fopen("profile.gp","wb");
        fd2=fopen("reference.gp","wb");
-       fd5=fopen("curvature.gp", "wb");
 
-       if (f)
-       {
-               fd3=fopen("fresnel.gp", "wb");
-               fd4=fopen("fresnel_pt_6.gp", "wb");
-       }
-
-       for (x=0; x<path.length; x++)
+       for (x=1; x<path.length-1; x++)
        {
                remote.lat=path.lat[x];
                remote.lon=path.lon[x];
                remote.alt=0.0;
+               angle=ElevationAngle(destination,remote);
 
-               terrain=GetElevation(remote);
-
-               if (x==0)
-                       terrain+=destination.alt;  /* RX antenna spike */
-
-               a=terrain+earthradius;
-               cangle=5280.0*Distance(destination,remote)/earthradius;
-               c=b*sin(refangle*deg2rad+HALFPI)/sin(HALFPI-refangle*deg2rad-cangle);
-
-               height=a-c;
-
-               /* Per Fink and Christiansen, Electronics
-                * Engineers' Handbook, 1989:
-                *
-                *   H = sqrt(lamba * d1 * (d - d1)/d)
-                *
-                * where H is the distance from the LOS
-                * path to the first Fresnel zone boundary.
-                */
-
-               if (f)
+               if (clutter>0.0)
                {
-                       d1=5280.0*path.distance[x];
-                       f_zone=-1*sqrt(lambda*d1*(d-d1)/d);
-                       fpt6_zone=0.6*f_zone;
-               }
+                       remote2.lat=path.lat[x];
+                       remote2.lon=path.lon[x];
 
-               if (n)
-               {
-                       r=-(nm*path.distance[x])-nb;
-                       height+=r;
+                       if (path.elevation[x]!=0.0)
+                               remote2.alt=clutter;
+                       else
+                               remote2.alt=0.0;
 
-                       if (f>0) 
-                       {
-                               f_zone+=r;
-                               fpt6_zone+=r;
-                       }
+                       clutter_angle=ElevationAngle(destination,remote2);
                }
 
-               else
-                       r=0.0;
-
                if (metric)
                {
-                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*height);
-                       fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*r);
-                       fprintf(fd5,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*(height-terrain));
-               }
+                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],angle);
 
-               else
-               {
-                       fprintf(fd,"%f\t%f\n",path.distance[x],height);
-                       fprintf(fd2,"%f\t%f\n",path.distance[x],r);
-                       fprintf(fd5,"%f\t%f\n",path.distance[x],height-terrain);
+                       if (fd1!=NULL)
+                               fprintf(fd1,"%f\t%f\n",KM_PER_MILE*path.distance[x],clutter_angle);
+
+                       fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[x],refangle);
                }
 
-               if (f)
+               else
                {
-                       if (metric)
-                       {
-                               fprintf(fd3,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*f_zone);
-                               fprintf(fd4,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*fpt6_zone);
-                       }
+                       fprintf(fd,"%f\t%f\n",path.distance[x],angle);
 
-                       else
-                       {
-                               fprintf(fd3,"%f\t%f\n",path.distance[x],f_zone);
-                               fprintf(fd4,"%f\t%f\n",path.distance[x],fpt6_zone);
-                       }
+                       if (fd1!=NULL)
+                               fprintf(fd1,"%f\t%f\n",path.distance[x],clutter_angle);
 
-                       if (f_zone<minheight)
-                               minheight=f_zone;
+                       fprintf(fd2,"%f\t%f\n",path.distance[x],refangle);
                }
 
-               if (height>maxheight)
-                       maxheight=height;
-
-               if (height<minheight)
-                       minheight=height;
-
-               if (r>maxheight)
-                       maxheight=r;
+               if (angle>maxangle)
+                       maxangle=angle;
 
-               if (terrain<minterrain)
-                       minterrain=terrain;
+               if (clutter_angle>maxangle)
+                       maxangle=clutter_angle;
 
-               if ((height-terrain)<minearth)
-                       minearth=height-terrain;
+               if (angle<minangle)
+                       minangle=angle;
        }
 
-       if (n)
-               r=-(nm*path.distance[path.length-1])-nb;
-       else
-               r=0.0;
-
        if (metric)
        {
-               fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
-               fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
-       }
-
-       else
-       {
-               fprintf(fd,"%f\t%f\n",path.distance[path.length-1],r);
-               fprintf(fd2,"%f\t%f\n",path.distance[path.length-1],r);
-       }
-
-       if (f)
-       {
-               if (metric)
-               {
-                       fprintf(fd3,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
-                       fprintf(fd4,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
-               }
-
-               else
-               {
-                       fprintf(fd3,"%f\t%f\n",path.distance[path.length-1],r);
-                       fprintf(fd4,"%f\t%f\n",path.distance[path.length-1],r);
-               }
+               fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],refangle);
+               fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],refangle);
        }
-       
-       if (r>maxheight)
-               maxheight=r;
 
-       if (r<minheight)
-               minheight=r;
+       else
+       {
+               fprintf(fd,"%f\t%f\n",path.distance[path.length-1],refangle);
+               fprintf(fd2,"%f\t%f\n",path.distance[path.length-1],refangle);
+       }
 
        fclose(fd);
-       fclose(fd2);
-       fclose(fd5);
 
-       if (f)
-       {
-               fclose(fd3);
-               fclose(fd4);
-       }
+       if (fd1!=NULL)
+               fclose(fd1);
 
-       if (name[0]==0)
+       fclose(fd2);
+
+       if (name[0]=='.')
        {
                /* Default filename and output file type */
 
-               strncpy(filename,"height\0",8);
+               strncpy(basename,"profile\0",8);
                strncpy(term,"png\0",4);
                strncpy(ext,"png\0",4);
        }
 
        else
        {
-               /* Grab extension and terminal type from "name" */
+               /* Extract extension and terminal type from "name" */
 
-               for (x=0; name[x]!='.' && name[x]!=0 && x<254; x++)
-                       filename[x]=name[x];
+               ext[0]=0;
+               y=strlen(name);
+               strncpy(basename,name,254);
 
-               if (name[x]=='.')
+               for (x=y-1; x>0 && name[x]!='.'; x--);
+
+               if (x>0)  /* Extension found */
                {
-                       for (y=0, z=x, x++; name[x]!=0 && x<254 && y<14; x++, y++)
+                       for (z=x+1; z<=y && (z-(x+1))<10; z++)
                        {
-                               term[y]=tolower(name[x]);
-                               ext[y]=term[y];
+                               ext[z-(x+1)]=tolower(name[z]);
+                               term[z-(x+1)]=name[z];
                        }
 
-                       ext[y]=0;
-                       term[y]=0;
-                       filename[z]=0;
+                       ext[z-(x+1)]=0;  /* Ensure an ending 0 */
+                       term[z-(x+1)]=0;
+                       basename[x]=0;
                }
 
-               else
-               {       /* No extension -- Default is png */
-
-                       filename[x]=0;
+               if (ext[0]==0)  /* No extension -- Default is png */
+               {
                        strncpy(term,"png\0",4);
                        strncpy(ext,"png\0",4);
                }
@@ -3977,94 +5539,58 @@ void GraphHeight(struct site source, struct site destination, char *name, double
                strncpy(ext,"ps\0",3);
 
        else if (strncmp(ext,"ps",2)==0)
-               strncpy(term,"postscript enhanced color\0",26);
-
-       fprintf(stdout,"Writing \"%s.%s\"...",filename,ext);
-       fflush(stdout);
+                       strncpy(term,"postscript enhanced color\0",26);
 
        fd=fopen("splat.gp","w");
 
-       dheight=maxheight-minheight;
-       miny=minheight-0.15*dheight;
-       maxy=maxheight+0.05*dheight;
-
-       if (maxy<20.0)
-               maxy=20.0;
-
-       dheight=maxheight-minheight;
-       min2y=miny-minterrain+0.05*dheight;
+       fprintf(fd,"set grid\n");
 
-       if (minearth<min2y)
-       {
-               miny-=min2y-minearth+0.05*dheight;
-               min2y=minearth-0.05*dheight;
-       }
+       if (distance>2.0)
+               fprintf(fd,"set yrange [%2.3f to %2.3f]\n", (-fabs(refangle)-0.25), maxangle+0.25);
+       else
+               fprintf(fd,"set yrange [%2.3f to %2.3f]\n", minangle, refangle+(-minangle/8.0));
 
-       max2y=min2y+maxy-miny;
-       fprintf(fd,"set grid\n");
-       fprintf(fd,"set yrange [%2.3f to %2.3f]\n", metric?miny*METERS_PER_FOOT:miny, metric?maxy*METERS_PER_FOOT:maxy);
-       fprintf(fd,"set y2range [%2.3f to %2.3f]\n", metric?min2y*METERS_PER_FOOT:min2y, metric?max2y*METERS_PER_FOOT:max2y);
-       fprintf(fd,"set xrange [-0.5 to %2.3f]\n",metric?KM_PER_MILE*rint(distance+0.5):rint(distance+0.5));
        fprintf(fd,"set encoding iso_8859_1\n");
        fprintf(fd,"set term %s\n",term);
-
-       if (f)
-               fprintf(fd,"set title \"SPLAT! Path Profile Between %s and %s (%.2f%c azimuth)\\nWith First Fresnel Zone\"\n",destination.name, source.name, azimuth,176);
-
-       else
-               fprintf(fd,"set title \"SPLAT! Height Profile Between %s and %s (%.2f%c azimuth)\"\n",destination.name, source.name, azimuth,176);
+       fprintf(fd,"set title \"%s Elevation Profile Between %s and %s (%.2f%c azimuth)\"\n",splat_name,destination.name,source.name,Azimuth(destination,source),176);
 
        if (metric)
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(source,destination));
+               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*distance);
        else
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(source,destination));
+               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,distance);
 
-       if (n)
-       {
-               if (metric)
-                       fprintf(fd,"set ylabel \"Normalized Height Referenced To LOS Path Between\\n%s and %s (meters)\"\n",destination.name,source.name);
-
-               else
-                       fprintf(fd,"set ylabel \"Normalized Height Referenced To LOS Path Between\\n%s and %s (feet)\"\n",destination.name,source.name);
 
-       }
+       fprintf(fd,"set ylabel \"Elevation Angle Along LOS Path Between\\n%s and %s (degrees)\"\n",destination.name,source.name);
+       fprintf(fd,"set output \"%s.%s\"\n",basename,ext);
 
-       else
+       if (clutter>0.0)
        {
                if (metric)
-                       fprintf(fd,"set ylabel \"Height Referenced To LOS Path Between %s and %s (meters)\"\n",destination.name,source.name);
-
+                       fprintf(fd,"plot \"profile.gp\" title \"Real Earth Profile\" with lines, \"clutter.gp\" title \"Clutter Profile (%.2f meters)\" with lines, \"reference.gp\" title \"Line of Sight Path (%.2f%c elevation)\" with lines\n",clutter*METERS_PER_FOOT,refangle,176);
                else
-                       fprintf(fd,"set ylabel \"Height Referenced To LOS Path Between %s and %s (feet)\"\n",destination.name,source.name);
+                       fprintf(fd,"plot \"profile.gp\" title \"Real Earth Profile\" with lines, \"clutter.gp\" title \"Clutter Profile (%.2f feet)\" with lines, \"reference.gp\" title \"Line of Sight Path (%.2f%c elevation)\" with lines\n",clutter,refangle,176);
        }
 
-       fprintf(fd,"set output \"%s.%s\"\n",filename,ext);
-
-       if (f)
-               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"reference.gp\" title \"Line of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines, \"fresnel.gp\" axes x1y1 title \"First Fresnel Zone (%.3f MHz)\" with lines, \"fresnel_pt_6.gp\" title \"60%% of First Fresnel Zone\" with lines\n",f);
-
        else
-               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"reference.gp\" title \"Line Of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines\n");
+               fprintf(fd,"plot \"profile.gp\" title \"Real Earth Profile\" with lines, \"reference.gp\" title \"Line of Sight Path (%.2f%c elevation)\" with lines\n",refangle,176);
 
        fclose(fd);
-
+                       
        x=system("gnuplot splat.gp");
 
        if (x!=-1)
        {
-               unlink("splat.gp");
-               unlink("profile.gp");
-               unlink("reference.gp");
-               unlink("curvature.gp");
-
-               if (f)
+               if (gpsav==0)
                {
-                       unlink("fresnel.gp");
-                       unlink("fresnel_pt_6.gp");
-               }
+                       unlink("splat.gp");
+                       unlink("profile.gp");
+                       unlink("reference.gp");
 
-               fprintf(stdout," Done!\n");
+                       if (clutter>0.0)
+                               unlink("clutter.gp");
+               }       
+
+               fprintf(stdout,"Elevation plot written to: \"%s.%s\"\n",basename,ext);
                fflush(stdout);
        }
 
@@ -4072,559 +5598,639 @@ void GraphHeight(struct site source, struct site destination, char *name, double
                fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
 }
 
-void GraphLongley(struct site source, struct site destination, char *name)
+void GraphHeight(struct site source, struct site destination, char *name, unsigned char fresnel_plot, unsigned char normalized)
 {
        /* This function invokes gnuplot to generate an appropriate
-          output file indicating the Longley-Rice model loss between
-          the source and destination locations.  "filename" is the
-          name assigned to the output file generated by gnuplot.
+          output file indicating the terrain height profile between
+          the source and destination locations referenced to the
+          line-of-sight path between the receive and transmit sites
+          when the -h or -H command line option is used.  "basename"
+          is the name assigned to the output file generated by gnuplot.
           The filename extension is used to set gnuplot's terminal
           setting and output file type.  If no extension is found,
-          .png is assumed. */
-
-       int     x, y, z, errnum, errflag=0;
-       char    filename[255], term[30], ext[15], strmode[100],
-               report_name[80], block=0;
-       double  maxloss=-100000.0, minloss=100000.0, loss, haavt,
-               angle1, angle2, azimuth, pattern=1.0, patterndB=0.0,
-               total_loss=0.0, cos_xmtr_angle, cos_test_angle=0.0,
-               source_alt, test_alt, dest_alt, source_alt2, dest_alt2,
-               distance, elevation, four_thirds_earth;
-       FILE    *fd=NULL, *fd2=NULL;
-
-       sprintf(report_name,"%s-to-%s.lro",source.name,destination.name);
+          .png is assumed.  */
 
-       four_thirds_earth=EARTHRADIUS*(4.0/3.0);
-
-       for (x=0; report_name[x]!=0; x++)
-               if (report_name[x]==32 || report_name[x]==17 || report_name[x]==92 || report_name[x]==42 || report_name[x]==47)
-                       report_name[x]='_';     
+       int     x, y, z;
+       char    basename[255], term[30], ext[15];
+       double  a, b, c, height=0.0, refangle, cangle, maxheight=-100000.0,
+               minheight=100000.0, lambda=0.0, f_zone=0.0, fpt6_zone=0.0,
+               nm=0.0, nb=0.0, ed=0.0, es=0.0, r=0.0, d=0.0, d1=0.0,
+               terrain, azimuth, distance, dheight=0.0, minterrain=100000.0,
+               minearth=100000.0, miny, maxy, min2y, max2y;
+       struct  site remote;
+       FILE    *fd=NULL, *fd1=NULL, *fd2=NULL, *fd3=NULL, *fd4=NULL, *fd5=NULL;
 
-       fd2=fopen(report_name,"w");
+       ReadPath(destination,source);  /* destination=RX, source=TX */
+       azimuth=Azimuth(destination,source);
+       distance=Distance(destination,source);
+       refangle=ElevationAngle(destination,source);
+       b=GetElevation(destination)+destination.alt+earthradius;
 
-       fprintf(fd2,"\n\t--==[ SPLAT! v%s Longley-Rice Model Path Loss Report ]==--\n\n",splat_version);
-       fprintf(fd2,"Analysis of RF path conditions between %s and %s:\n",source.name, destination.name);
-       fprintf(fd2,"\n-------------------------------------------------------------------------\n\n");
-       fprintf(fd2,"Transmitter site: %s\n",source.name);
+       /* Wavelength and path distance (great circle) in feet. */
 
-       if (source.lat>=0.0)
+       if (fresnel_plot)
        {
-               fprintf(fd2,"Site location: %.4f North / %.4f West",source.lat, source.lon);
-               fprintf(fd2, " (%s N / ", dec2dms(source.lat));
+               lambda=9.8425e8/(LR.frq_mhz*1e6);
+               d=5280.0*path.distance[path.length-1];
        }
 
-       else
+       if (normalized)
        {
-
-               fprintf(fd2,"Site location: %.4f South / %.4f West",-source.lat, source.lon);
-               fprintf(fd2, " (%s S / ", dec2dms(source.lat));
+               ed=GetElevation(destination);
+               es=GetElevation(source);
+               nb=-destination.alt-ed;
+               nm=(-source.alt-es-nb)/(path.distance[path.length-1]);
        }
-       
-       fprintf(fd2, "%s W)\n", dec2dms(source.lon));
 
-       if (metric)
-       {
-               fprintf(fd2,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(source));
-               fprintf(fd2,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*source.alt,METERS_PER_FOOT*(source.alt+GetElevation(source)));
-       }
+       fd=fopen("profile.gp","wb");
 
-       else
-       {
-               fprintf(fd2,"Ground elevation: %.2f feet AMSL\n",GetElevation(source));
-               fprintf(fd2,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",source.alt, source.alt+GetElevation(source));
-       }
+       if (clutter>0.0)
+               fd1=fopen("clutter.gp","wb");
 
-       haavt=haat(source);
+       fd2=fopen("reference.gp","wb");
+       fd5=fopen("curvature.gp", "wb");
 
-       if (haavt>-4999.0)
+       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
        {
-               if (metric)
-                       fprintf(fd2,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
-               else
-                       fprintf(fd2,"Antenna height above average terrain: %.2f feet\n",haavt);
+               fd3=fopen("fresnel.gp", "wb");
+               fd4=fopen("fresnel_pt_6.gp", "wb");
        }
 
-       azimuth=Azimuth(source,destination);
-       angle1=ElevationAngle(source,destination);
-       angle2=ElevationAngle2(source,destination,earthradius);
-
-       if (got_azimuth_pattern || got_elevation_pattern)
+       for (x=0; x<path.length-1; x++)
        {
-               x=(int)rint(10.0*(10.0-angle2));
+               remote.lat=path.lat[x];
+               remote.lon=path.lon[x];
+               remote.alt=0.0;
 
-               if (x>=0 && x<=1000)
-                       pattern=(double)LR.antenna_pattern[(int)rint(azimuth)][x];
+               terrain=GetElevation(remote);
 
-               patterndB=20.0*log10(pattern);
+               if (x==0)
+                       terrain+=destination.alt;  /* RX antenna spike */
 
-               fprintf(fd2,"Antenna pattern between %s and %s: %.3f (%.2f dB)\n",source.name, destination.name, pattern, patterndB);
+               a=terrain+earthradius;
+               cangle=5280.0*Distance(destination,remote)/earthradius;
+               c=b*sin(refangle*DEG2RAD+HALFPI)/sin(HALFPI-refangle*DEG2RAD-cangle);
 
-       }
+               height=a-c;
 
-       if (metric)
-               fprintf(fd2,"Distance to %s: %.2f kilometers\n",destination.name,METERS_PER_FOOT*Distance(source,destination));
+               /* Per Fink and Christiansen, Electronics
+                * Engineers' Handbook, 1989:
+                *
+                *   H = sqrt(lamba * d1 * (d - d1)/d)
+                *
+                * where H is the distance from the LOS
+                * path to the first Fresnel zone boundary.
+                */
 
-       else
-               fprintf(fd2,"Distance to %s: %.2f miles.\n",destination.name,Distance(source,destination));
+               if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+               {
+                       d1=5280.0*path.distance[x];
+                       f_zone=-1.0*sqrt(lambda*d1*(d-d1)/d);
+                       fpt6_zone=f_zone*fzone_clearance;
+               }
 
-       fprintf(fd2,"Azimuth to %s: %.2f degrees\n",destination.name,azimuth);
+               if (normalized)
+               {
+                       r=-(nm*path.distance[x])-nb;
+                       height+=r;
 
-       if (angle1>=0.0)
-               fprintf(fd2,"Elevation angle to %s: %+.4f degrees\n",destination.name,angle1);
+                       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+                       {
+                               f_zone+=r;
+                               fpt6_zone+=r;
+                       }
+               }
 
-       else
-               fprintf(fd2,"Depression angle to %s: %+.4f degrees\n",destination.name,angle1);
+               else
+                       r=0.0;
+
+               if (metric)
+               {
+                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*height);
+
+                       if (fd1!=NULL && x>0 && x<path.length-2)
+                               fprintf(fd1,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*(terrain==0.0?height:(height+clutter)));
+
+                       fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*r);
+                       fprintf(fd5,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*(height-terrain));
+               }
 
-       if (angle1!=angle2)
-       {
-               if (angle2<0.0)
-                       fprintf(fd2,"Depression");
                else
-                       fprintf(fd2,"Elevation");
+               {
+                       fprintf(fd,"%f\t%f\n",path.distance[x],height);
 
-               fprintf(fd2," angle to the first obstruction: %+.4f degrees\n",angle2);
-       }
+                       if (fd1!=NULL && x>0 && x<path.length-2)
+                               fprintf(fd1,"%f\t%f\n",path.distance[x],(terrain==0.0?height:(height+clutter)));
 
-       fprintf(fd2,"\n-------------------------------------------------------------------------\n\n");
+                       fprintf(fd2,"%f\t%f\n",path.distance[x],r);
+                       fprintf(fd5,"%f\t%f\n",path.distance[x],height-terrain);
+               }
 
-       /* Receiver */
+               if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+               {
+                       if (metric)
+                       {
+                               fprintf(fd3,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*f_zone);
+                               fprintf(fd4,"%f\t%f\n",KM_PER_MILE*path.distance[x],METERS_PER_FOOT*fpt6_zone);
+                       }
 
-       fprintf(fd2,"Receiver site: %s\n",destination.name);
+                       else
+                       {
+                               fprintf(fd3,"%f\t%f\n",path.distance[x],f_zone);
+                               fprintf(fd4,"%f\t%f\n",path.distance[x],fpt6_zone);
+                       }
 
-       if (destination.lat>=0.0)
-       {
-               fprintf(fd2,"Site location: %.4f North / %.4f West",destination.lat, destination.lon);
-               fprintf(fd2, " (%s N / ", dec2dms(destination.lat));
-       }
+                       if (f_zone<minheight)
+                               minheight=f_zone;
+               }
 
-       else
-       {
-               fprintf(fd2,"Site location: %.4f South / %.4f West",-destination.lat, destination.lon);
-               fprintf(fd2, " (%s S / ", dec2dms(destination.lat));
+               if ((height+clutter)>maxheight)
+                       maxheight=height+clutter;
+
+               if (height<minheight)
+                       minheight=height;
+
+               if (r>maxheight)
+                       maxheight=r;
+
+               if (terrain<minterrain)
+                       minterrain=terrain;
+
+               if ((height-terrain)<minearth)
+                       minearth=height-terrain;
        }
 
-       fprintf(fd2, "%s W)\n", dec2dms(destination.lon));
+       if (normalized)
+               r=-(nm*path.distance[path.length-1])-nb;
+       else
+               r=0.0;
 
        if (metric)
        {
-               fprintf(fd2,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(destination));
-               fprintf(fd2,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*destination.alt, METERS_PER_FOOT*(destination.alt+GetElevation(destination)));
+               fprintf(fd,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
+               fprintf(fd2,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
        }
 
        else
        {
-               fprintf(fd2,"Ground elevation: %.2f feet AMSL\n",GetElevation(destination));
-               fprintf(fd2,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",destination.alt, destination.alt+GetElevation(destination));
+               fprintf(fd,"%f\t%f\n",path.distance[path.length-1],r);
+               fprintf(fd2,"%f\t%f\n",path.distance[path.length-1],r);
        }
 
-       haavt=haat(destination);
-
-       if (haavt>-4999.0)
+       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
        {
                if (metric)
-                       fprintf(fd2,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
+               {
+                       fprintf(fd3,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
+                       fprintf(fd4,"%f\t%f\n",KM_PER_MILE*path.distance[path.length-1],METERS_PER_FOOT*r);
+               }
+
                else
-                       fprintf(fd2,"Antenna height above average terrain: %.2f feet\n",haavt);
+               {
+                       fprintf(fd3,"%f\t%f\n",path.distance[path.length-1],r);
+                       fprintf(fd4,"%f\t%f\n",path.distance[path.length-1],r);
+               }
        }
+       
+       if (r>maxheight)
+               maxheight=r;
 
-       if (metric)
-               fprintf(fd2,"Distance to %s: %.2f kilometers\n",source.name,KM_PER_MILE*Distance(source,destination));
-
-       else
-               fprintf(fd2,"Distance to %s: %.2f miles\n",source.name,Distance(source,destination));
-
-       azimuth=Azimuth(destination,source);
-
-       angle1=ElevationAngle(destination,source);
-       angle2=ElevationAngle2(destination,source,earthradius);
+       if (r<minheight)
+               minheight=r;
 
-       fprintf(fd2,"Azimuth to %s: %.2f degrees.\n",source.name,azimuth);
+       fclose(fd);
 
-       if (angle1>=0.0)
-               fprintf(fd2,"Elevation angle to %s: %+.4f degrees\n",source.name,angle1);
+       if (fd1!=NULL)
+               fclose(fd1);
 
-       else
-               fprintf(fd2,"Depression angle to %s: %+.4f degrees\n",source.name,angle1);
+       fclose(fd2);
+       fclose(fd5);
 
-       if (angle1!=angle2)
+       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
        {
-               if (angle2<0.0)
-                       fprintf(fd2,"Depression");
-               else
-                       fprintf(fd2,"Elevation");
-
-               fprintf(fd2," angle to the first obstruction: %+.4f degrees\n",angle2);
+               fclose(fd3);
+               fclose(fd4);
        }
 
-       fprintf(fd2,"\n-------------------------------------------------------------------------\n\n");
+       if (name[0]=='.')
+       {
+               /* Default filename and output file type */
 
-       fprintf(fd2,"Longley-Rice path calculation parameters used in this analysis:\n\n");
-       fprintf(fd2,"Earth's Dielectric Constant: %.3lf\n",LR.eps_dielect);
-       fprintf(fd2,"Earth's Conductivity: %.3lf\n",LR.sgm_conductivity);
-       fprintf(fd2,"Atmospheric Bending Constant (N): %.3lf\n",LR.eno_ns_surfref);
-       fprintf(fd2,"Frequency: %.3lf (MHz)\n",LR.frq_mhz);
-       fprintf(fd2,"Radio Climate: %d (",LR.radio_climate);
+               strncpy(basename,"profile\0",8);
+               strncpy(term,"png\0",4);
+               strncpy(ext,"png\0",4);
+       }
 
-       switch (LR.radio_climate)
+       else
        {
-               case 1:
-               fprintf(fd2,"Equatorial");
-               break;
+               /* Extract extension and terminal type from "name" */
 
-               case 2:
-               fprintf(fd2,"Continental Subtropical");
-               break;
+               ext[0]=0;
+               y=strlen(name);
+               strncpy(basename,name,254);
 
-               case 3:
-               fprintf(fd2,"Maritime Subtropical");
-               break;
+               for (x=y-1; x>0 && name[x]!='.'; x--);
 
-               case 4:
-               fprintf(fd2,"Desert");
-               break;
+               if (x>0)  /* Extension found */
+               {
+                       for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                       {
+                               ext[z-(x+1)]=tolower(name[z]);
+                               term[z-(x+1)]=name[z];
+                       }
 
-               case 5:
-               fprintf(fd2,"Continental Temperate");
-               break;
+                       ext[z-(x+1)]=0;  /* Ensure an ending 0 */
+                       term[z-(x+1)]=0;
+                       basename[x]=0;
+               }
 
-               case 6:
-               fprintf(fd2,"Martitime Temperate, Over Land");
-               break;
+               if (ext[0]==0)  /* No extension -- Default is png */
+               {
+                       strncpy(term,"png\0",4);
+                       strncpy(ext,"png\0",4);
+               }
+       }
 
-               case 7:
-               fprintf(fd2,"Maritime Temperate, Over Sea");
-               break;
+       /* Either .ps or .postscript may be used
+          as an extension for postscript output. */
 
-               default:
-               fprintf(fd2,"Unknown");
-       }
+       if (strncmp(term,"postscript",10)==0)
+               strncpy(ext,"ps\0",3);
+
+       else if (strncmp(ext,"ps",2)==0)
+                       strncpy(term,"postscript enhanced color\0",26);
 
-       fprintf(fd2,")\nPolarization: %d (",LR.pol);
+       fd=fopen("splat.gp","w");
 
-       if (LR.pol==0)
-               fprintf(fd2,"Horizontal");
+       dheight=maxheight-minheight;
+       miny=minheight-0.15*dheight;
+       maxy=maxheight+0.05*dheight;
 
-       if (LR.pol==1)
-               fprintf(fd2,"Vertical");
+       if (maxy<20.0)
+               maxy=20.0;
 
-       fprintf(fd2,")\nFraction of Situations: %.1lf%c\n",LR.conf*100.0,37);
-       fprintf(fd2,"Fraction of Time: %.1lf%c\n",LR.rel*100.0,37);
-       fprintf(fd2,"\n-------------------------------------------------------------------------\n\n");
+       dheight=maxheight-minheight;
+       min2y=miny-minterrain+0.05*dheight;
 
-       fprintf(fd2,"Analysis Results:\n\n");
+       if (minearth<min2y)
+       {
+               miny-=min2y-minearth+0.05*dheight;
+               min2y=minearth-0.05*dheight;
+       }
 
-       ReadPath(source, destination);  /* source=TX, destination=RX */
+       max2y=min2y+maxy-miny;
+       fprintf(fd,"set grid\n");
+       fprintf(fd,"set yrange [%2.3f to %2.3f]\n", metric?miny*METERS_PER_FOOT:miny, metric?maxy*METERS_PER_FOOT:maxy);
+       fprintf(fd,"set y2range [%2.3f to %2.3f]\n", metric?min2y*METERS_PER_FOOT:min2y, metric?max2y*METERS_PER_FOOT:max2y);
+       fprintf(fd,"set xrange [-0.5 to %2.3f]\n",metric?KM_PER_MILE*rint(distance+0.5):rint(distance+0.5));
+       fprintf(fd,"set encoding iso_8859_1\n");
+       fprintf(fd,"set term %s\n",term);
 
-       /* Copy elevations along path into the elev_l[] array. */
+       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+               fprintf(fd,"set title \"%s Path Profile Between %s and %s (%.2f%c azimuth)\\nWith First Fresnel Zone\"\n",splat_name, destination.name, source.name, azimuth,176);
 
-       for (x=0; x<path.length; x++)
-               elev_l[x+2]=path.elevation[x]*METERS_PER_FOOT;  
+       else
+               fprintf(fd,"set title \"%s Height Profile Between %s and %s (%.2f%c azimuth)\"\n",splat_name, destination.name, source.name, azimuth,176);
 
        if (metric)
-               fprintf(fd2,"Distance (km)");
+               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(source,destination));
        else
-               fprintf(fd2,"Distance (mi)");
+               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(source,destination));
 
-       fprintf(fd2,"\tLoss (dB)\tErrnum\tComment\n\n");
+       if (normalized)
+       {
+               if (metric)
+                       fprintf(fd,"set ylabel \"Normalized Height Referenced To LOS Path Between\\n%s and %s (meters)\"\n",destination.name,source.name);
 
-       fd=fopen("profile.gp","w");
+               else
+                       fprintf(fd,"set ylabel \"Normalized Height Referenced To LOS Path Between\\n%s and %s (feet)\"\n",destination.name,source.name);
 
-       azimuth=rint(Azimuth(source,destination));
+       }
 
-       for (y=2; y<(path.length-1); y++)  /* path.length-1 avoids LR error */
+       else
        {
-               distance=5280.0*path.distance[y];
-               source_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;
-               source_alt2=source_alt*source_alt;
+               if (metric)
+                       fprintf(fd,"set ylabel \"Height Referenced To LOS Path Between\\n%s and %s (meters)\"\n",destination.name,source.name);
 
-               /* Calculate the cosine of the elevation of
-                  the receiver as seen by the transmitter. */
+               else
+                       fprintf(fd,"set ylabel \"Height Referenced To LOS Path Between\\n%s and %s (feet)\"\n",destination.name,source.name);
+       }
 
-               cos_xmtr_angle=((source_alt2)+(distance*distance)-(dest_alt2))/(2.0*source_alt*distance);
+       fprintf(fd,"set output \"%s.%s\"\n",basename,ext);
 
-               if (got_elevation_pattern)
+       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+       {
+               if (clutter>0.0)
                {
-                       /* If an antenna elevation pattern is available, the
-                          following code determines the elevation angle to
-                          the first obstruction along the path. */
-
-                       for (x=2, block=0; x<y && block==0; x++)
-                       {
-                               distance=5280.0*(path.distance[y]-path.distance[x]);
-                               test_alt=four_thirds_earth+path.elevation[x];
-
-                               /* Calculate the cosine of the elevation
-                                  angle of the terrain (test point)
-                                  as seen by the transmitter. */
-
-                               cos_test_angle=((source_alt2)+(distance*distance)-(test_alt*test_alt))/(2.0*source_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 sense of the
-                                  following "if" statement is reversed from
-                                  what it would be if the angles themselves
-                                  were compared. */
-
-                               if (cos_xmtr_angle>cos_test_angle)
-                                       block=1;
-                       }
-
-                       /* At this point, we have the elevation angle
-                          to the first obstruction (if it exists). */
+                       if (metric)
+                               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"clutter.gp\" title \"Ground Clutter (%.2f meters)\" with lines, \"reference.gp\" title \"Line of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines, \"fresnel.gp\" axes x1y1 title \"First Fresnel Zone (%.3f MHz)\" with lines, \"fresnel_pt_6.gp\" title \"%.0f%% of First Fresnel Zone\" with lines\n",clutter*METERS_PER_FOOT,LR.frq_mhz,fzone_clearance*100.0);
+                       else
+                               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"clutter.gp\" title \"Ground Clutter (%.2f feet)\" with lines, \"reference.gp\" title \"Line of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines, \"fresnel.gp\" axes x1y1 title \"First Fresnel Zone (%.3f MHz)\" with lines, \"fresnel_pt_6.gp\" title \"%.0f%% of First Fresnel Zone\" with lines\n",clutter,LR.frq_mhz,fzone_clearance*100.0);
                }
 
-               /* Determine path loss for each point along the
-                  path using Longley-Rice's point_to_point mode
-                  starting at x=2 (number_of_points = 1), the
-                  shortest distance terrain can play a role in
-                  path loss. */
-
-               elev_l[0]=y-1;  /* (number of points - 1) */
-
-               /* Distance between elevation samples */
-               elev_l[1]=METERS_PER_MILE*(path.distance[y]-path.distance[y-1]);
-
-               point_to_point(elev_l, 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 (block)
-                       elevation=((acos(cos_test_angle))/deg2rad)-90.0;
                else
-                       elevation=((acos(cos_xmtr_angle))/deg2rad)-90.0;
-
-               /* Integrate the antenna's radiation
-                  pattern into the overall path loss. */
-
-               x=(int)rint(10.0*(10.0-elevation));
+                       fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"reference.gp\" title \"Line of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines, \"fresnel.gp\" axes x1y1 title \"First Fresnel Zone (%.3f MHz)\" with lines, \"fresnel_pt_6.gp\" title \"%.0f%% of First Fresnel Zone\" with lines\n",LR.frq_mhz,fzone_clearance*100.0);
+       }
 
-               if (x>=0 && x<=1000)
+       else
+       {
+               if (clutter>0.0)
                {
-                       pattern=(double)LR.antenna_pattern[(int)azimuth][x];
-
-                       if (pattern!=0.0)
-                               patterndB=20.0*log10(pattern);
+                       if (metric)
+                               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"clutter.gp\" title \"Ground Clutter (%.2f meters)\" with lines, \"reference.gp\" title \"Line Of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines\n",clutter*METERS_PER_FOOT);
+                       else
+                               fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"clutter.gp\" title \"Ground Clutter (%.2f feet)\" with lines, \"reference.gp\" title \"Line Of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines\n",clutter);
                }
 
                else
-                       patterndB=0.0;
+                       fprintf(fd,"plot \"profile.gp\" title \"Point-to-Point Profile\" with lines, \"reference.gp\" title \"Line Of Sight Path\" with lines, \"curvature.gp\" axes x1y2 title \"Earth's Curvature Contour\" with lines\n");
 
-               total_loss=loss-patterndB;
+       }
 
-               if (metric)
-               {
-                       fprintf(fd,"%f\t%f\n",KM_PER_MILE*(path.distance[path.length-1]-path.distance[y]),total_loss);
-                       fprintf(fd2,"%7.2f\t\t%7.2f\t\t  %d\t%s\n",KM_PER_MILE*path.distance[y],total_loss, errnum, strmode);
-               }
+       fclose(fd);
 
-               else
+       x=system("gnuplot splat.gp");
+
+       if (x!=-1)
+       {
+               if (gpsav==0)
                {
-                       fprintf(fd,"%f\t%f\n",path.distance[path.length-1]-path.distance[y],total_loss);
-                       fprintf(fd2,"%7.2f\t\t%7.2f\t\t  %d\t%s\n",path.distance[y],total_loss, errnum, strmode);
-               }
+                       unlink("splat.gp");
+                       unlink("profile.gp");
+                       unlink("reference.gp");
+                       unlink("curvature.gp");
 
-               errflag|=errnum;
+                       if (fd1!=NULL)
+                               unlink("clutter.gp");
 
-               if (total_loss>maxloss)
-                       maxloss=total_loss;
+                       if ((LR.frq_mhz>=20.0) && (LR.frq_mhz<=20000.0) && fresnel_plot)
+                       {
+                               unlink("fresnel.gp");
+                               unlink("fresnel_pt_6.gp");
+                       }
+               }
 
-               if (total_loss<minloss)
-                       minloss=total_loss;
+               fprintf(stdout,"\nHeight plot written to: \"%s.%s\"",basename,ext);
+               fflush(stdout);
        }
 
-       fclose(fd);
+       else
+               fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
+}
 
-       fprintf(fd2,"\nLongley-Rice path loss between %s and %s is %.2f dB.\n",source.name, destination.name, loss);
+void ObstructionAnalysis(struct site xmtr, struct site rcvr, double f, FILE *outfile)
+{
+       /* Perform an obstruction analysis along the
+          path between receiver and transmitter. */
+
+       int     x;
+       struct  site site_x;
+       double  h_r, h_t, h_x, h_r_orig, cos_tx_angle, cos_test_angle,
+               cos_tx_angle_f1, cos_tx_angle_fpt6, d_tx, d_x,
+               h_r_f1, h_r_fpt6, h_f, h_los, lambda=0.0;
+       char    string[255], string_fpt6[255], string_f1[255];
+
+       ReadPath(xmtr,rcvr);
+       h_r=GetElevation(rcvr)+rcvr.alt+earthradius;
+       h_r_f1=h_r;
+       h_r_fpt6=h_r;
+       h_r_orig=h_r;
+       h_t=GetElevation(xmtr)+xmtr.alt+earthradius;
+       d_tx=5280.0*Distance(rcvr,xmtr);
+       cos_tx_angle=((h_r*h_r)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r*d_tx);
+       cos_tx_angle_f1=cos_tx_angle;
+       cos_tx_angle_fpt6=cos_tx_angle;
 
-       if (patterndB!=0.0)
-               fprintf(fd2,"Total path loss including TX antenna pattern is %.2f dB.\n",total_loss);
+       if (f)
+               lambda=9.8425e8/(f*1e6);
 
-       if (errflag)
+       if (clutter>0.0)
        {
-               fprintf(fd2,"\nNotes on \"errnum\":\n\n");
-               fprintf(fd2,"  0: No error.  :-)\n");
-               fprintf(fd2,"  1: Warning!  Some parameters are nearly out of range.\n");
-               fprintf(fd2,"     Results should be used with caution.\n");
-               fprintf(fd2,"  2: Note: Default parameters have been substituted for impossible ones.\n");
-               fprintf(fd2,"  3: Warning!  A combination of parameters is out of range.\n");
-               fprintf(fd2,"     Results are probably invalid.\n");
-               fprintf(fd2,"  Other: Warning!  Some parameters are out of range.\n");
-               fprintf(fd2,"    Results are probably invalid.\n\nEnd of Report\n");
-       }
+               fprintf(outfile,"Terrain has been raised by");
 
-       fprintf(stdout,"Longley-Rice path loss between %s and %s is %.2f dB.\n",source.name, destination.name, loss);
+               if (metric)
+                       fprintf(outfile," %.2f meters",METERS_PER_FOOT*clutter);
+               else
+                       fprintf(outfile," %.2f feet",clutter);
 
-       if (patterndB!=0.0)
-               fprintf(stdout,"Total path loss including TX antenna pattern is %.2f dB.\n",total_loss);
+               fprintf(outfile," to account for ground clutter.\n\n");
+       }
 
-       fprintf(stdout,"Path Loss Report written to: \"%s\"\n",report_name);
-       fflush(stdout);
+       /* At each point along the path calculate the cosine
+          of a sort of "inverse elevation angle" at the receiver.
+          From the antenna, 0 deg. looks at the ground, and 90 deg.
+          is parallel to the ground.
 
-       fclose(fd2);
+          Start at the receiver.  If this is the lowest antenna,
+          then terrain obstructions will be nearest to it.  (Plus,
+          that's the way SPLAT!'s original los() did it.)
+
+          Calculate cosines only.  That's sufficient to compare
+          angles and it saves the extra computational burden of
+          acos().  However, note the inverted comparison: if
+          acos(A) > acos(B), then B > A. */
 
-       if (name[0]==0)
+       for (x=path.length-1; x>0; x--)
        {
-               /* Default filename and output file type */
+               site_x.lat=path.lat[x];
+               site_x.lon=path.lon[x];
+               site_x.alt=0.0;
 
-               strncpy(filename,"loss\0",5);
-               strncpy(term,"png\0",4);
-               strncpy(ext,"png\0",4);
-       }
+               h_x=GetElevation(site_x)+earthradius+clutter;
+               d_x=5280.0*Distance(rcvr,site_x);
 
-       else
-       {
-               /* Grab extension and terminal type from "name" */
+               /* Deal with the LOS path first. */
 
-               for (x=0; name[x]!='.' && name[x]!=0 && x<254; x++)
-                       filename[x]=name[x];
+               cos_test_angle=((h_r*h_r)+(d_x*d_x)-(h_x*h_x))/(2.0*h_r*d_x);
 
-               if (name[x]=='.')
+               if (cos_tx_angle>cos_test_angle)
                {
-                       for (y=0, z=x, x++; name[x]!=0 && x<254 && y<14; x++, y++)
+                       if (h_r==h_r_orig)
+                               fprintf(outfile,"Between %s and %s, %s detected obstructions at:\n\n",rcvr.name,xmtr.name,splat_name);
+
+                       if (site_x.lat>=0.0)
                        {
-                               term[y]=tolower(name[x]);
-                               ext[y]=term[y];
+                               if (metric)
+                                       fprintf(outfile,"   %8.4f N,%9.4f W, %5.2f kilometers, %6.2f meters AMSL\n",site_x.lat, site_x.lon, KM_PER_MILE*(d_x/5280.0), METERS_PER_FOOT*(h_x-earthradius));
+                               else
+                                       fprintf(outfile,"   %8.4f N,%9.4f W, %5.2f miles, %6.2f feet AMSL\n",site_x.lat, site_x.lon, d_x/5280.0, h_x-earthradius);
                        }
 
-                       ext[y]=0;
-                       term[y]=0;
-                       filename[z]=0;
-               }
+                       else
+                       {
+                               if (metric)
+                                       fprintf(outfile,"   %8.4f S,%9.4f W, %5.2f kilometers, %6.2f meters AMSL\n",-site_x.lat, site_x.lon, KM_PER_MILE*(d_x/5280.0), METERS_PER_FOOT*(h_x-earthradius));
+                               else
 
-               else
-               {       /* No extension -- Default is png */
+                                       fprintf(outfile,"   %8.4f S,%9.4f W, %5.2f miles, %6.2f feet AMSL\n",-site_x.lat, site_x.lon, d_x/5280.0, h_x-earthradius);
+                       }
+               }
 
-                       filename[x]=0;
-                       strncpy(term,"png\0",4);
-                       strncpy(ext,"png\0",4);
+               while (cos_tx_angle>cos_test_angle)
+               {
+                       h_r+=1;
+                       cos_test_angle=((h_r*h_r)+(d_x*d_x)-(h_x*h_x))/(2.0*h_r*d_x);
+                       cos_tx_angle=((h_r*h_r)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r*d_tx);
                }
-       }
 
-       /* Either .ps or .postscript may be used
-          as an extension for postscript output. */
+               if (f)
+               {
+                       /* Now clear the first Fresnel zone... */
 
-       if (strncmp(term,"postscript",10)==0)
-               strncpy(ext,"ps\0",3);
+                       cos_tx_angle_f1=((h_r_f1*h_r_f1)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_f1*d_tx);
+                       h_los=sqrt(h_r_f1*h_r_f1+d_x*d_x-2*h_r_f1*d_x*cos_tx_angle_f1);
+                       h_f=h_los-sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
 
-       else if (strncmp(ext,"ps",2)==0)
-               strncpy(term,"postscript enhanced color\0",26);
+                       while (h_f<h_x)
+                       {
+                               h_r_f1+=1;
+                               cos_tx_angle_f1=((h_r_f1*h_r_f1)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_f1*d_tx);
+                               h_los=sqrt(h_r_f1*h_r_f1+d_x*d_x-2*h_r_f1*d_x*cos_tx_angle_f1);
+                               h_f=h_los-sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
+                       }
 
-       fprintf(stdout,"Writing \"%s.%s\"...",filename,ext);
-       fflush(stdout);
+                       /* and clear the 60% F1 zone. */
 
-       fd=fopen("splat.gp","w");
+                       cos_tx_angle_fpt6=((h_r_fpt6*h_r_fpt6)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_fpt6*d_tx);
+                       h_los=sqrt(h_r_fpt6*h_r_fpt6+d_x*d_x-2*h_r_fpt6*d_x*cos_tx_angle_fpt6);
+                       h_f=h_los-fzone_clearance*sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
 
-       fprintf(fd,"set grid\n");
-       fprintf(fd,"set yrange [%2.3f to %2.3f]\n", minloss, maxloss);
-       fprintf(fd,"set encoding iso_8859_1\n");
-       fprintf(fd,"set term %s\n",term);
-       fprintf(fd,"set title \"SPLAT! Loss Profile Along Path Between %s and %s (%.2f%c azimuth)\"\n",destination.name, source.name, Azimuth(destination,source),176);
+                       while (h_f<h_x)
+                       {
+                               h_r_fpt6+=1;
+                               cos_tx_angle_fpt6=((h_r_fpt6*h_r_fpt6)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_fpt6*d_tx);
+                               h_los=sqrt(h_r_fpt6*h_r_fpt6+d_x*d_x-2*h_r_fpt6*d_x*cos_tx_angle_fpt6);
+                               h_f=h_los-fzone_clearance*sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
+                       }
+               }
+       }
+               
+       if (h_r>h_r_orig)
+       {
+               if (metric)
+                       snprintf(string,150,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear all obstructions detected by %s.\n",rcvr.name, METERS_PER_FOOT*(h_r-GetElevation(rcvr)-earthradius),splat_name);
+               else
+                       snprintf(string,150,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear all obstructions detected by %s.\n",rcvr.name, h_r-GetElevation(rcvr)-earthradius,splat_name);
+       }
 
-       if (metric)
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(destination,source));
        else
-               fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(destination,source));
+               snprintf(string,150,"\nNo obstructions to LOS path due to terrain were detected by %s\n",splat_name);
 
-       if (got_azimuth_pattern || got_elevation_pattern)
-               fprintf(fd,"set ylabel \"Total Path Loss (including TX antenna pattern) (dB)");
-       else
-               fprintf(fd,"set ylabel \"Longley-Rice Path Loss (dB)");
+       if (f)
+       {
+               if (h_r_fpt6>h_r_orig)
+               {
+                       if (metric)
+                               snprintf(string_fpt6,150,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear %.0f%c of the first Fresnel zone.\n",rcvr.name, METERS_PER_FOOT*(h_r_fpt6-GetElevation(rcvr)-earthradius),fzone_clearance*100.0,37);
+
+                       else
+                               snprintf(string_fpt6,150,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear %.0f%c of the first Fresnel zone.\n",rcvr.name, h_r_fpt6-GetElevation(rcvr)-earthradius,fzone_clearance*100.0,37);
+               }
 
-       fprintf(fd,"\"\nset output \"%s.%s\"\n",filename,ext);
-       fprintf(fd,"plot \"profile.gp\" title \"Path Loss\" with lines\n");
+               else
+                       snprintf(string_fpt6,150,"\n%.0f%c of the first Fresnel zone is clear.\n",fzone_clearance*100.0,37);
+       
+               if (h_r_f1>h_r_orig)
+               {
+                       if (metric)
+                               snprintf(string_f1,150,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear the first Fresnel zone.\n",rcvr.name, METERS_PER_FOOT*(h_r_f1-GetElevation(rcvr)-earthradius));
 
-       fclose(fd);
-                       
-       x=system("gnuplot splat.gp");
+                       else                    
+                               snprintf(string_f1,150,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear the first Fresnel zone.\n",rcvr.name, h_r_f1-GetElevation(rcvr)-earthradius);
 
-       if (x!=-1)
-       {
-               unlink("splat.gp");
-               unlink("profile.gp");
-               unlink("reference.gp"); 
+               }
 
-               fprintf(stdout," Done!\n");
-               fflush(stdout);
+               else
+                   snprintf(string_f1,150,"\nThe first Fresnel zone is clear.\n");
        }
 
-       else
-               fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
+       fprintf(outfile,"%s",string);
+
+       if (f)
+       {
+               fprintf(outfile,"%s",string_f1);
+               fprintf(outfile,"%s",string_fpt6);
+       }
 }
 
-void ObstructionReport(struct site xmtr, struct site rcvr, char report, double f)
+void PathReport(struct site source, struct site destination, char *name, char graph_it)
 {
-       int     x;
-       struct  site site_x;
-       double  h_r, h_t, h_x, h_r_orig, cos_tx_angle, cos_test_angle,
-               cos_tx_angle_f1, cos_tx_angle_fpt6, haavt, d_tx, d_x,
-               h_r_f1, h_r_fpt6, h_f, h_los, lambda=0.0, azimuth,
-               pattern, patterndB, distance, angle1, angle2;
-       char    report_name[80], string[255], string_fpt6[255],
-               string_f1[255];
-       FILE    *fd;
+       /* This function writes a SPLAT! Path Report (name.txt) to
+          the filesystem.  If (graph_it == 1), then gnuplot is invoked
+          to generate an appropriate output file indicating the Longley-Rice
+          model loss between the source and destination locations.
+          "filename" is the name assigned to the output file generated
+          by gnuplot.  The filename extension is used to set gnuplot's
+          terminal setting and output file type.  If no extension is
+          found, .png is assumed. */
+
+       int     x, y, z, errnum;
+       char    basename[255], term[30], ext[15], strmode[100],
+               report_name[80], block=0;
+       double  maxloss=-100000.0, minloss=100000.0, loss, haavt,
+               angle1, angle2, azimuth, pattern=1.0, patterndB=0.0,
+               total_loss=0.0, cos_xmtr_angle, cos_test_angle=0.0,
+               source_alt, test_alt, dest_alt, source_alt2, dest_alt2,
+               distance, elevation, four_thirds_earth, field_strength,
+               free_space_loss=0.0, eirp=0.0, voltage, rxp, dBm,
+               power_density;
+       FILE    *fd=NULL, *fd2=NULL;
 
-       sprintf(report_name,"%s-to-%s.txt",xmtr.name,rcvr.name);
+       sprintf(report_name,"%s-to-%s.txt",source.name,destination.name);
+
+       four_thirds_earth=FOUR_THIRDS*EARTHRADIUS;
 
        for (x=0; report_name[x]!=0; x++)
                if (report_name[x]==32 || report_name[x]==17 || report_name[x]==92 || report_name[x]==42 || report_name[x]==47)
                        report_name[x]='_';     
 
-       fd=fopen(report_name,"w");
-
-       fprintf(fd,"\n\t\t--==[ SPLAT! v%s Obstruction Report ]==--\n\n",splat_version);
-       fprintf(fd,"Analysis of great circle path between %s and %s:\n",xmtr.name, rcvr.name);
-       fprintf(fd,"\n-------------------------------------------------------------------------\n\n");
-       fprintf(fd,"Transmitter site: %s\n",xmtr.name);
+       fd2=fopen(report_name,"w");
 
+       fprintf(fd2,"\n\t\t--==[ %s v%s Path Analysis ]==--\n\n",splat_name,splat_version);
+       fprintf(fd2,"%s\n\n",dashes);
+       fprintf(fd2,"Transmitter site: %s\n",source.name);
 
-       if (xmtr.lat>=0.0)
+       if (source.lat>=0.0)
        {
-               fprintf(fd,"Site location: %.4f North / %.4f West",xmtr.lat, xmtr.lon);
-               fprintf(fd, " (%s N / ", dec2dms(xmtr.lat));
+               fprintf(fd2,"Site location: %.4f North / %.4f West",source.lat, source.lon);
+               fprintf(fd2, " (%s N / ", dec2dms(source.lat));
        }
 
        else
        {
-               fprintf(fd,"Site location: %.4f South / %.4f West",-xmtr.lat, xmtr.lon);
-               fprintf(fd, " (%s S / ", dec2dms(xmtr.lat));
-       }
 
-       fprintf(fd, "%s W)\n", dec2dms(xmtr.lon));
+               fprintf(fd2,"Site location: %.4f South / %.4f West",-source.lat, source.lon);
+               fprintf(fd2, " (%s S / ", dec2dms(source.lat));
+       }
+       
+       fprintf(fd2, "%s W)\n", dec2dms(source.lon));
 
        if (metric)
        {
-               fprintf(fd,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(xmtr));
-               fprintf(fd,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*xmtr.alt, METERS_PER_FOOT*(xmtr.alt+GetElevation(xmtr)));
+               fprintf(fd2,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(source));
+               fprintf(fd2,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*source.alt,METERS_PER_FOOT*(source.alt+GetElevation(source)));
        }
 
        else
        {
-               fprintf(fd,"Ground elevation: %.2f feet AMSL\n",GetElevation(xmtr));
-               fprintf(fd,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",xmtr.alt, xmtr.alt+GetElevation(xmtr));
+               fprintf(fd2,"Ground elevation: %.2f feet AMSL\n",GetElevation(source));
+               fprintf(fd2,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",source.alt, source.alt+GetElevation(source));
        }
 
-       haavt=haat(xmtr);
+       haavt=haat(source);
 
        if (haavt>-4999.0)
        {
                if (metric)
-                       fprintf(fd,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
+                       fprintf(fd2,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
                else
-                       fprintf(fd,"Antenna height above average terrain: %.2f feet\n",haavt);
+                       fprintf(fd2,"Antenna height above average terrain: %.2f feet\n",haavt);
        }
 
-       pattern=1.0;
-       patterndB=0.0;
-       distance=Distance(xmtr,rcvr);
-       azimuth=Azimuth(xmtr,rcvr);
-       angle1=ElevationAngle(xmtr,rcvr);
-       angle2=ElevationAngle2(xmtr,rcvr,earthradius);
+       azimuth=Azimuth(source,destination);
+       angle1=ElevationAngle(source,destination);
+       angle2=ElevationAngle2(source,destination,earthradius);
 
        if (got_azimuth_pattern || got_elevation_pattern)
        {
@@ -4633,288 +6239,501 @@ void ObstructionReport(struct site xmtr, struct site rcvr, char report, double f
                if (x>=0 && x<=1000)
                        pattern=(double)LR.antenna_pattern[(int)rint(azimuth)][x];
 
-               if (pattern!=1.0)
-               {
-                       fprintf(fd,"Antenna pattern toward %s: %.3f",rcvr.name,pattern);
-                       patterndB=20.0*log10(pattern);
-                       fprintf(fd," (%.2f dB)\n",patterndB);
-               }
+               patterndB=20.0*log10(pattern);
        }
 
        if (metric)
-               fprintf(fd,"Distance to %s: %.2f kilometers\n",rcvr.name,KM_PER_MILE*distance);
+               fprintf(fd2,"Distance to %s: %.2f kilometers\n",destination.name,KM_PER_MILE*Distance(source,destination));
 
        else
-               fprintf(fd,"Distance to %s: %.2f miles\n",rcvr.name,distance);
+               fprintf(fd2,"Distance to %s: %.2f miles\n",destination.name,Distance(source,destination));
 
-       fprintf(fd,"Azimuth to %s: %.2f degrees\n",rcvr.name,azimuth);
+       fprintf(fd2,"Azimuth to %s: %.2f degrees\n",destination.name,azimuth);
 
        if (angle1>=0.0)
-               fprintf(fd,"Elevation angle to %s: %+.4f degrees\n",rcvr.name,angle1);
+               fprintf(fd2,"Elevation angle to %s: %+.4f degrees\n",destination.name,angle1);
 
        else
-               fprintf(fd,"Depression angle to %s: %+.4f degrees\n",rcvr.name,angle1);
+               fprintf(fd2,"Depression angle to %s: %+.4f degrees\n",destination.name,angle1);
 
-       if (angle1!=angle2)
+       if ((angle2-angle1)>0.0001)
        {
                if (angle2<0.0)
-                       fprintf(fd,"Depression");
+                       fprintf(fd2,"Depression");
                else
-                       fprintf(fd,"Elevation");
+                       fprintf(fd2,"Elevation");
 
-               fprintf(fd," angle to the first obstruction: %+.4f degrees\n",angle2);
+               fprintf(fd2," angle to the first obstruction: %+.4f degrees\n",angle2);
        }
 
-       fprintf(fd,"\n-------------------------------------------------------------------------\n\n");
+       fprintf(fd2,"\n%s\n\n",dashes);
 
        /* Receiver */
 
-       fprintf(fd,"Receiver site: %s\n",rcvr.name);
+       fprintf(fd2,"Receiver site: %s\n",destination.name);
 
-       if (rcvr.lat>=0.0)
+       if (destination.lat>=0.0)
        {
-               fprintf(fd,"Site location: %.4f North / %.4f West",rcvr.lat, rcvr.lon);
-               fprintf(fd, " (%s N / ", dec2dms(rcvr.lat));
+               fprintf(fd2,"Site location: %.4f North / %.4f West",destination.lat, destination.lon);
+               fprintf(fd2, " (%s N / ", dec2dms(destination.lat));
        }
 
        else
        {
-               fprintf(fd,"Site location: %.4f South / %.4f West",-rcvr.lat, rcvr.lon);
-               fprintf(fd, " (%s S / ", dec2dms(rcvr.lat));
+               fprintf(fd2,"Site location: %.4f South / %.4f West",-destination.lat, destination.lon);
+               fprintf(fd2, " (%s S / ", dec2dms(destination.lat));
        }
 
-       fprintf(fd, "%s W)\n", dec2dms(rcvr.lon));
+       fprintf(fd2, "%s W)\n", dec2dms(destination.lon));
 
        if (metric)
        {
-               fprintf(fd,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(rcvr));
-               fprintf(fd,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*rcvr.alt, METERS_PER_FOOT*(rcvr.alt+GetElevation(rcvr)));
+               fprintf(fd2,"Ground elevation: %.2f meters AMSL\n",METERS_PER_FOOT*GetElevation(destination));
+               fprintf(fd2,"Antenna height: %.2f meters AGL / %.2f meters AMSL\n",METERS_PER_FOOT*destination.alt, METERS_PER_FOOT*(destination.alt+GetElevation(destination)));
        }
 
        else
        {
-               fprintf(fd,"Ground elevation: %.2f feet AMSL\n",GetElevation(rcvr));
-               fprintf(fd,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",rcvr.alt, rcvr.alt+GetElevation(rcvr));
+               fprintf(fd2,"Ground elevation: %.2f feet AMSL\n",GetElevation(destination));
+               fprintf(fd2,"Antenna height: %.2f feet AGL / %.2f feet AMSL\n",destination.alt, destination.alt+GetElevation(destination));
        }
 
-       haavt=haat(rcvr);
+       haavt=haat(destination);
 
        if (haavt>-4999.0)
        {
                if (metric)
-                       fprintf(fd,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
+                       fprintf(fd2,"Antenna height above average terrain: %.2f meters\n",METERS_PER_FOOT*haavt);
                else
-                       fprintf(fd,"Antenna height above average terrain: %.2f feet\n",haavt);
+                       fprintf(fd2,"Antenna height above average terrain: %.2f feet\n",haavt);
        }
 
-       azimuth=Azimuth(rcvr,xmtr);
-       angle1=ElevationAngle(rcvr,xmtr);
-       angle2=ElevationAngle2(rcvr,xmtr,earthradius);
-
        if (metric)
-               fprintf(fd,"Distance to %s: %.2f kilometers\n",xmtr.name,KM_PER_MILE*distance);
+               fprintf(fd2,"Distance to %s: %.2f kilometers\n",source.name,KM_PER_MILE*Distance(source,destination));
+
        else
-               fprintf(fd,"Distance to %s: %.2f miles\n",xmtr.name,distance);
+               fprintf(fd2,"Distance to %s: %.2f miles\n",source.name,Distance(source,destination));
+
+       azimuth=Azimuth(destination,source);
 
-       fprintf(fd,"Azimuth to %s: %.2f degrees\n",xmtr.name,azimuth);
+       angle1=ElevationAngle(destination,source);
+       angle2=ElevationAngle2(destination,source,earthradius);
+
+       fprintf(fd2,"Azimuth to %s: %.2f degrees\n",source.name,azimuth);
 
        if (angle1>=0.0)
-               fprintf(fd,"Elevation to %s: %+.4f degrees\n",xmtr.name,angle1);
+               fprintf(fd2,"Elevation angle to %s: %+.4f degrees\n",source.name,angle1);
 
        else
-               fprintf(fd,"Depression angle to %s: %+.4f degrees\n",xmtr.name,angle1);
+               fprintf(fd2,"Depression angle to %s: %+.4f degrees\n",source.name,angle1);
 
-       if (angle1!=angle2)
+       if ((angle2-angle1)>0.0001)
        {
                if (angle2<0.0)
-                       fprintf(fd,"Depression");
+                       fprintf(fd2,"Depression");
                else
-                       fprintf(fd,"Elevation");
-
-               fprintf(fd," angle to the first obstruction: %+.4f degrees\n",angle2);
+                       fprintf(fd2,"Elevation");
 
+               fprintf(fd2," angle to the first obstruction: %+.4f degrees\n",angle2);
        }
 
-       fprintf(fd,"\n-------------------------------------------------------------------------\n\n");
+       fprintf(fd2,"\n%s\n\n",dashes);
 
-       if (report=='y')
+       if (LR.frq_mhz>0.0)
        {
-               /* Generate profile of the terrain.  Create the path
-                  from transmitter to receiver because that's the
-                  way the original los() function did it, and going
-                  the other way can yield slightly different results. */
+               fprintf(fd2,"Longley-Rice path calculation parameters used in this analysis:\n\n");
+               fprintf(fd2,"Earth's Dielectric Constant: %.3lf\n",LR.eps_dielect);
+               fprintf(fd2,"Earth's Conductivity: %.3lf Siemens/meter\n",LR.sgm_conductivity);
+               fprintf(fd2,"Atmospheric Bending Constant (N-units): %.3lf ppm\n",LR.eno_ns_surfref);
+               fprintf(fd2,"Frequency: %.3lf MHz\n",LR.frq_mhz);
+               fprintf(fd2,"Radio Climate: %d (",LR.radio_climate);
 
-               ReadPath(xmtr,rcvr);
-               h_r=GetElevation(rcvr)+rcvr.alt+earthradius;
-               h_r_f1=h_r;
-               h_r_fpt6=h_r;
-               h_r_orig=h_r;
-               h_t=GetElevation(xmtr)+xmtr.alt+earthradius;
-               d_tx=5280.0*Distance(rcvr,xmtr);
-               cos_tx_angle=((h_r*h_r)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r*d_tx);
-               cos_tx_angle_f1=cos_tx_angle;
-               cos_tx_angle_fpt6=cos_tx_angle;
+               switch (LR.radio_climate)
+               {
+                       case 1:
+                       fprintf(fd2,"Equatorial");
+                       break;
 
-               if (f)
-                       lambda=9.8425e8/(f*1e6);
+                       case 2:
+                       fprintf(fd2,"Continental Subtropical");
+                       break;
 
-               /* At each point along the path calculate the cosine
-                  of a sort of "inverse elevation angle" at the receiver.
-                  From the antenna, 0 deg. looks at the ground, and 90 deg.
-                  is parallel to the ground.
+                       case 3:
+                       fprintf(fd2,"Maritime Subtropical");
+                       break;
 
-                  Start at the receiver.  If this is the lowest antenna,
-                  then terrain obstructions will be nearest to it.  (Plus,
-                  that's the way the original los() did it.)
+                       case 4:
+                       fprintf(fd2,"Desert");
+                       break;
 
-                  Calculate cosines only.  That's sufficient to compare
-                  angles and it saves the extra computational burden of
-                  acos().  However, note the inverted comparison: if
-                  acos(A) > acos(B), then B > A. */
-               
-               for (x=path.length-1; x>0; x--)
+                       case 5:
+                       fprintf(fd2,"Continental Temperate");
+                       break;
+
+                       case 6:
+                       fprintf(fd2,"Martitime Temperate, Over Land");
+                       break;
+
+                       case 7:
+                       fprintf(fd2,"Maritime Temperate, Over Sea");
+                       break;
+
+                       default:
+                       fprintf(fd2,"Unknown");
+               }
+
+               fprintf(fd2,")\nPolarization: %d (",LR.pol);
+
+               if (LR.pol==0)
+                       fprintf(fd2,"Horizontal");
+
+               if (LR.pol==1)
+                       fprintf(fd2,"Vertical");
+
+               fprintf(fd2,")\nFraction of Situations: %.1lf%c\n",LR.conf*100.0,37);
+               fprintf(fd2,"Fraction of Time: %.1lf%c\n",LR.rel*100.0,37);
+
+               if (LR.erp!=0.0)
                {
-                       site_x.lat=path.lat[x];
-                       site_x.lon=path.lon[x];
-                       site_x.alt=0.0;
+                       fprintf(fd2,"Transmitter ERP: ");
 
-                       h_x=GetElevation(site_x)+earthradius;
-                       d_x=5280.0*Distance(rcvr,site_x);
+                       if (LR.erp<1.0)
+                               fprintf(fd2,"%.1lf milliwatts",1000.0*LR.erp);
 
-                       /* Deal with the LOS path first. */
+                       if (LR.erp>=1.0 && LR.erp<10.0)
+                               fprintf(fd2,"%.1lf Watts",LR.erp);
 
-                       cos_test_angle=((h_r*h_r)+(d_x*d_x)-(h_x*h_x))/(2.0*h_r*d_x);
+                       if (LR.erp>=10.0 && LR.erp<10.0e3)
+                               fprintf(fd2,"%.0lf Watts",LR.erp);
+
+                       if (LR.erp>=10.0e3)
+                               fprintf(fd2,"%.3lf kilowatts",LR.erp/1.0e3);
+
+                       dBm=10.0*(log10(LR.erp*1000.0));
+                       fprintf(fd2," (%+.2f dBm)\n",dBm);
+
+                       /* EIRP = ERP + 2.14 dB */
+
+                       fprintf(fd2,"Transmitter EIRP: ");
+
+                       eirp=LR.erp*1.636816521;
+
+                       if (eirp<1.0)
+                               fprintf(fd2,"%.1lf milliwatts",1000.0*eirp);
+
+                       if (eirp>=1.0 && eirp<10.0)
+                               fprintf(fd2,"%.1lf Watts",eirp);
 
-                       if (cos_tx_angle>cos_test_angle)
+                       if (eirp>=10.0 && eirp<10.0e3)
+                               fprintf(fd2,"%.0lf Watts",eirp);
+
+                       if (eirp>=10.0e3)
+                               fprintf(fd2,"%.3lf kilowatts",eirp/1.0e3);
+
+                       dBm=10.0*(log10(eirp*1000.0));
+                       fprintf(fd2," (%+.2f dBm)\n",dBm);
+               }
+
+               fprintf(fd2,"\n%s\n\n",dashes);
+
+               fprintf(fd2,"Summary for the link between %s and %s:\n\n",source.name, destination.name);
+
+               if (patterndB!=0.0)
+                       fprintf(fd2,"%s antenna pattern towards %s: %.3f (%.2f dB)\n", source.name, destination.name, pattern, patterndB);
+
+               ReadPath(source, destination);  /* source=TX, destination=RX */
+
+               /* Copy elevations plus clutter along
+                  path into the elev[] array. */
+
+               for (x=1; x<path.length-1; x++)
+                       elev[x+2]=METERS_PER_FOOT*(path.elevation[x]==0.0?path.elevation[x]:(clutter+path.elevation[x]));
+
+               /* 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;
+
+               fd=fopen("profile.gp","w");
+
+               azimuth=rint(Azimuth(source,destination));
+
+               for (y=2; y<(path.length-1); y++)  /* path.length-1 avoids LR error */
+               {
+                       distance=5280.0*path.distance[y];
+                       source_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;
+                       source_alt2=source_alt*source_alt;
+
+                       /* Calculate the cosine of the elevation of
+                          the receiver as seen by the transmitter. */
+
+                       cos_xmtr_angle=((source_alt2)+(distance*distance)-(dest_alt2))/(2.0*source_alt*distance);
+
+                       if (got_elevation_pattern)
                        {
-                               if (h_r==h_r_orig)
-                                       fprintf(fd,"SPLAT! detected obstructions at:\n\n");
+                               /* If an antenna elevation pattern is available, the
+                                  following code determines the elevation angle to
+                                  the first obstruction along the path. */
 
-                               if (site_x.lat>=0.0)
+                               for (x=2, block=0; x<y && block==0; x++)
                                {
-                                       if (metric)
-                                               fprintf(fd,"\t%.4f N, %.4f W, %5.2f kilometers, %6.2f meters AMSL\n",site_x.lat, site_x.lon, KM_PER_MILE*(d_x/5280.0), METERS_PER_FOOT*(h_x-earthradius));
-                                       else
-                                               fprintf(fd,"\t%.4f N, %.4f W, %5.2f miles, %6.2f feet AMSL\n",site_x.lat, site_x.lon, d_x/5280.0, h_x-earthradius);
-                               }
+                                       distance=5280.0*(path.distance[y]-path.distance[x]);
+                                       test_alt=four_thirds_earth+path.elevation[x];
 
-                               else
-                               {
-                                       if (metric)
-                                               fprintf(fd,"\t%.4f S, %.4f W, %5.2f kilometers, %6.2f meters AMSL\n",-site_x.lat, site_x.lon, KM_PER_MILE*(d_x/5280.0), METERS_PER_FOOT*(h_x-earthradius));
-                                       else
+                                       /* Calculate the cosine of the elevation
+                                          angle of the terrain (test point)
+                                          as seen by the transmitter. */
+
+                                       cos_test_angle=((source_alt2)+(distance*distance)-(test_alt*test_alt))/(2.0*source_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 sense of the
+                                          following "if" statement is reversed from
+                                          what it would be if the angles themselves
+                                          were compared. */
 
-                                               fprintf(fd,"\t%.4f S, %.4f W, %5.2f miles, %6.2f feet AMSL\n",-site_x.lat, site_x.lon, d_x/5280.0, h_x-earthradius);
+                                       if (cos_xmtr_angle>=cos_test_angle)
+                                               block=1;
                                }
+
+                               /* At this point, we have the elevation angle
+                                  to the first obstruction (if it exists). */
                        }
 
-                       while (cos_tx_angle>cos_test_angle)
+                       /* Determine path loss for each point along the
+                          path using Longley-Rice's point_to_point mode
+                          starting at x=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]);
+
+                       point_to_point(elev, source.alt*METERS_PER_FOOT, 
+                       destination.alt*METERS_PER_FOOT, LR.eps_dielect,
+                       LR.sgm_conductivity, LR.eno_ns_surfref, LR.frq_mhz,
+                       LR.radio_climate, LR.pol, LR.conf, LR.rel, loss,
+                       strmode, errnum);
+
+                       if (block)
+                               elevation=((acos(cos_test_angle))/DEG2RAD)-90.0;
+                       else
+                               elevation=((acos(cos_xmtr_angle))/DEG2RAD)-90.0;
+
+                       /* Integrate the antenna's radiation
+                          pattern into the overall path loss. */
+
+                       x=(int)rint(10.0*(10.0-elevation));
+
+                       if (x>=0 && x<=1000)
                        {
-                               h_r+=1;
-                               cos_test_angle=((h_r*h_r)+(d_x*d_x)-(h_x*h_x))/(2.0*h_r*d_x);
-                               cos_tx_angle=((h_r*h_r)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r*d_tx);
+                               pattern=(double)LR.antenna_pattern[(int)azimuth][x];
+
+                               if (pattern!=0.0)
+                                       patterndB=20.0*log10(pattern);
                        }
 
-                       if (f)
-                       {
-                               /* Now clear the first Fresnel zone, but don't
-                                  clutter the obstruction report. */
+                       else
+                               patterndB=0.0;
 
-                               cos_tx_angle_f1=((h_r_f1*h_r_f1)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_f1*d_tx);
-                               h_los=sqrt(h_r_f1*h_r_f1+d_x*d_x-2*h_r_f1*d_x*cos_tx_angle_f1);
-                               h_f=h_los-sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
+                       total_loss=loss-patterndB;
 
-                               while (h_f<h_x)
-                               {
-                                       h_r_f1+=1;
-                                       cos_tx_angle_f1=((h_r_f1*h_r_f1)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_f1*d_tx);
-                                       h_los=sqrt(h_r_f1*h_r_f1+d_x*d_x-2*h_r_f1*d_x*cos_tx_angle_f1);
-                                       h_f=h_los-sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
-                               }
+                       if (metric)
+                               fprintf(fd,"%f\t%f\n",KM_PER_MILE*(path.distance[path.length-1]-path.distance[y]),total_loss);
 
-                               /* And clear the 60% F1 zone. */
+                       else
+                               fprintf(fd,"%f\t%f\n",path.distance[path.length-1]-path.distance[y],total_loss);
 
-                               cos_tx_angle_fpt6=((h_r_fpt6*h_r_fpt6)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_fpt6*d_tx);
-                               h_los=sqrt(h_r_fpt6*h_r_fpt6+d_x*d_x-2*h_r_fpt6*d_x*cos_tx_angle_fpt6);
-                               h_f=h_los-0.6*sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
+                       if (total_loss>maxloss)
+                               maxloss=total_loss;
 
-                               while (h_f<h_x)
-                               {
-                                       h_r_fpt6+=1;
-                                       cos_tx_angle_fpt6=((h_r_fpt6*h_r_fpt6)+(d_tx*d_tx)-(h_t*h_t))/(2.0*h_r_fpt6*d_tx);
-                                       h_los=sqrt(h_r_fpt6*h_r_fpt6+d_x*d_x-2*h_r_fpt6*d_x*cos_tx_angle_fpt6);
-                                       h_f=h_los-0.6*sqrt(lambda*d_x*(d_tx-d_x)/d_tx);
-                               }
-                       }
+                       if (total_loss<minloss)
+                               minloss=total_loss;
                }
-               
-               if (h_r>h_r_orig)
+
+               fclose(fd);
+
+               distance=Distance(source,destination);
+
+
+               if (distance!=0.0)
                {
-                       if (metric)
-                               sprintf(string,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear all obstructions detected by SPLAT!\n",rcvr.name, METERS_PER_FOOT*(h_r-GetElevation(rcvr)-earthradius));
-                       else
-                               sprintf(string,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear all obstructions detected by SPLAT!\n",rcvr.name, h_r-GetElevation(rcvr)-earthradius);
+                       free_space_loss=36.6+(20.0*log10(LR.frq_mhz))+(20.0*log10(distance));
+
+                       fprintf(fd2,"Free space path loss: %.2f dB\n",free_space_loss);
                }
 
-               else
-                       sprintf(string,"\nNo obstructions to LOS path due to terrain were detected by SPLAT!\n");
+               fprintf(fd2,"Longley-Rice path loss: %.2f dB\n",loss);
 
-               if (f)
+               if (free_space_loss!=0.0)
+                       fprintf(fd2,"Attenuation due to terrain shielding: %.2f dB\n",loss-free_space_loss);
+
+               if (patterndB!=0.0)
+                       fprintf(fd2,"Total path loss including %s antenna pattern: %.2f dB\n",source.name,total_loss);
+
+               if (LR.erp!=0.0)
                {
-                       if (h_r_fpt6>h_r_orig)
-                       {
-                               if (metric)
-                                       sprintf(string_fpt6,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear 60%c of the first Fresnel zone.\n",rcvr.name, METERS_PER_FOOT*(h_r_fpt6-GetElevation(rcvr)-earthradius),37);
+                       field_strength=(139.4+(20.0*log10(LR.frq_mhz))-total_loss)+(10.0*log10(LR.erp/1000.0));
 
-                               else
-                                       sprintf(string_fpt6,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear 60%c of the first Fresnel zone.\n",rcvr.name, h_r_fpt6-GetElevation(rcvr)-earthradius,37);
-                       }
+                       /* dBm is referenced to EIRP */
 
-                       else
-                               sprintf(string_fpt6,"\n60%c of the first Fresnel zone is clear.\n",37);
-       
-                       if (h_r_f1>h_r_orig)
-                       {
-                               if (metric)
-                                       sprintf(string_f1,"\nAntenna at %s must be raised to at least %.2f meters AGL\nto clear the first Fresnel zone.\n",rcvr.name, METERS_PER_FOOT*(h_r_f1-GetElevation(rcvr)-earthradius));
+                       rxp=eirp/(pow(10.0,(total_loss/10.0)));
+                       dBm=10.0*(log10(rxp*1000.0));
+                       power_density=(eirp/(pow(10.0,(total_loss-free_space_loss)/10.0)));
+                       /* divide by 4*PI*distance_in_meters squared */
+                       power_density/=(4.0*PI*distance*distance*2589988.11);
 
-                               else                    
-                                       sprintf(string_f1,"\nAntenna at %s must be raised to at least %.2f feet AGL\nto clear the first Fresnel zone.\n",rcvr.name, h_r_f1-GetElevation(rcvr)-earthradius);
+                       fprintf(fd2,"Field strength at %s: %.2f dBuV/meter\n", destination.name,field_strength);
+                       fprintf(fd2,"Signal power level at %s: %+.2f dBm\n",destination.name,dBm);
+                       fprintf(fd2,"Signal power density at %s: %+.2f dBW per square meter\n",destination.name,10.0*log10(power_density));
+                       voltage=1.0e6*sqrt(50.0*(eirp/(pow(10.0,(total_loss-2.14)/10.0))));
+                       fprintf(fd2,"Voltage across 50 ohm dipole at %s: %.2f uV (%.2f dBuV)\n",destination.name,voltage,20.0*log10(voltage));
 
-                       }
+                       voltage=1.0e6*sqrt(75.0*(eirp/(pow(10.0,(total_loss-2.14)/10.0))));
+                       fprintf(fd2,"Voltage across 75 ohm dipole at %s: %.2f uV (%.2f dBuV)\n",destination.name,voltage,20.0*log10(voltage));
+               }
 
-                       else
-                           sprintf(string_f1,"\nThe first Fresnel zone is clear.\n\n");
+               fprintf(fd2,"Mode of propagation: %s\n",strmode);
+               fprintf(fd2,"Longley-Rice model error number: %d",errnum);
+
+               switch (errnum)
+               {
+                       case 0:
+                               fprintf(fd2," (No error)\n");
+                               break;
+
+                       case 1:
+                               fprintf(fd2,"\n  Warning: Some parameters are nearly out of range.\n");
+                               fprintf(fd2,"  Results should be used with caution.\n");
+                               break;
+
+                       case 2:
+                               fprintf(fd2,"\n  Note: Default parameters have been substituted for impossible ones.\n");
+                               break;
+
+                       case 3:
+                               fprintf(fd2,"\n  Warning: A combination of parameters is out of range.\n");
+                               fprintf(fd2,"  Results are probably invalid.\n");
+                               break;
+
+                       default:
+                               fprintf(fd2,"\n  Warning: Some parameters are out of range.\n");
+                               fprintf(fd2,"  Results are probably invalid.\n");
                }
-       }
-       
-       fprintf(fd,"%s",string);
 
-       if (f)
-       {
-               fprintf(fd,"%s",string_f1);
-               fprintf(fd,"%s",string_fpt6);
+               fprintf(fd2,"\n%s\n\n",dashes);
        }
 
-       fclose(fd);
+       fprintf(stdout,"\nPath Loss Report written to: \"%s\"\n",report_name);
+       fflush(stdout);
 
-       /* Display report summary on terminal */
+       ObstructionAnalysis(source, destination, LR.frq_mhz, fd2);
 
-       /* Line-of-sight status */
+       fclose(fd2);
 
-       fprintf(stdout,"%s",string);
+       /* Skip plotting the graph if ONLY a path-loss report is needed. */
 
-       if (f)
+       if (graph_it)
        {
-               /* Fresnel zone status */
+               if (name[0]=='.')
+               {
+                       /* Default filename and output file type */
+
+                       strncpy(basename,"profile\0",8);
+                       strncpy(term,"png\0",4);
+                       strncpy(ext,"png\0",4);
+               }
+
+               else
+               {
+                       /* Extract extension and terminal type from "name" */
+
+                       ext[0]=0;
+                       y=strlen(name);
+                       strncpy(basename,name,254);
+
+                       for (x=y-1; x>0 && name[x]!='.'; x--);
+
+                       if (x>0)  /* Extension found */
+                       {
+                               for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                               {
+                                       ext[z-(x+1)]=tolower(name[z]);
+                                       term[z-(x+1)]=name[z];
+                               }
+
+                               ext[z-(x+1)]=0;  /* Ensure an ending 0 */
+                               term[z-(x+1)]=0;
+                               basename[x]=0;
+                       }
+               }
+
+               if (ext[0]==0)  /* No extension -- Default is png */
+               {
+                       strncpy(term,"png\0",4);
+                       strncpy(ext,"png\0",4);
+               }
+
+               /* Either .ps or .postscript may be used
+                  as an extension for postscript output. */
+
+               if (strncmp(term,"postscript",10)==0)
+                       strncpy(ext,"ps\0",3);
+
+               else if (strncmp(ext,"ps",2)==0)
+                               strncpy(term,"postscript enhanced color\0",26);
+
+               fd=fopen("splat.gp","w");
+
+               fprintf(fd,"set grid\n");
+               fprintf(fd,"set yrange [%2.3f to %2.3f]\n", minloss, maxloss);
+               fprintf(fd,"set encoding iso_8859_1\n");
+               fprintf(fd,"set term %s\n",term);
+               fprintf(fd,"set title \"%s Loss Profile Along Path Between %s and %s (%.2f%c azimuth)\"\n",splat_name, destination.name, source.name, Azimuth(destination,source),176);
+
+               if (metric)
+                       fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f kilometers)\"\n",destination.name,source.name,KM_PER_MILE*Distance(destination,source));
+               else
+                       fprintf(fd,"set xlabel \"Distance Between %s and %s (%.2f miles)\"\n",destination.name,source.name,Distance(destination,source));
+
+               if (got_azimuth_pattern || got_elevation_pattern)
+                       fprintf(fd,"set ylabel \"Total Path Loss (including TX antenna pattern) (dB)");
+               else
+                       fprintf(fd,"set ylabel \"Longley-Rice Path Loss (dB)");
+
+               fprintf(fd,"\"\nset output \"%s.%s\"\n",basename,ext);
+               fprintf(fd,"plot \"profile.gp\" title \"Path Loss\" with lines\n");
+
+               fclose(fd);
+                       
+               x=system("gnuplot splat.gp");
+
+               if (x!=-1)
+               {
+                       if (gpsav==0)
+                       {
+                               unlink("splat.gp");
+                               unlink("profile.gp");
+                               unlink("reference.gp");
+                       }       
+
+                       fprintf(stdout,"Path loss plot written to: \"%s.%s\"\n",basename,ext);
+                       fflush(stdout);
+               }
 
-               fprintf(stdout,"%s",string_f1);
-               fprintf(stdout,"%s",string_fpt6);
+               else
+                       fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
        }
 
-       fprintf(stdout, "\nObstruction report written to: \"%s\"\n",report_name);
-
-       fflush(stdout);
+       if (x!=-1 && gpsav==0)
+               unlink("profile.gp");
 }
 
 void SiteReport(struct site xmtr)
@@ -4932,9 +6751,9 @@ void SiteReport(struct site xmtr)
 
        fd=fopen(report_name,"w");
 
-       fprintf(fd,"\n\t--==[ SPLAT! v%s Site Analysis Report For: %s ]==--\n\n",splat_version,xmtr.name);
+       fprintf(fd,"\n\t--==[ %s v%s Site Analysis Report For: %s ]==--\n\n",splat_name, splat_version, xmtr.name);
 
-       fprintf(fd,"---------------------------------------------------------------------------\n\n");
+       fprintf(fd,"%s\n\n",dashes);
 
        if (xmtr.lat>=0.0)
        {
@@ -4993,7 +6812,7 @@ void SiteReport(struct site xmtr)
                }
        }
 
-       fprintf(fd,"\n---------------------------------------------------------------------------\n\n");
+       fprintf(fd,"\n%s\n\n",dashes);
        fclose(fd);
        fprintf(stdout,"\nSite analysis report written to: \"%s\"\n",report_name);
 }
@@ -5003,7 +6822,7 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat)
        /* This function loads the SDF files required
           to cover the limits of the region specified. */ 
 
-       int     x, y, width, ymin, ymax;
+       int x, y, width, ymin, ymax;
 
        width=ReduceAngle(max_lon-min_lon);
 
@@ -5028,7 +6847,10 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat)
                                while (ymax>=360)
                                        ymax-=360;
 
-                               sprintf(string,"%d:%d:%d:%d",x, x+1, ymin, ymax);
+                               if (ippd==3600)
+                                       snprintf(string,19,"%d:%d:%d:%d-hd",x, x+1, ymin, ymax);
+                               else
+                                       snprintf(string,16,"%d:%d:%d:%d",x, x+1, ymin, ymax);
                                LoadSDF(string);
                        }
        }
@@ -5054,25 +6876,31 @@ void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat)
                                while (ymax>=360)
                                        ymax-=360;
 
-                               sprintf(string,"%d:%d:%d:%d",x, x+1, ymin, ymax);
+                               if (ippd==3600)
+                                       snprintf(string,19,"%d:%d:%d:%d-hd",x, x+1, ymin, ymax);
+                               else
+                                       snprintf(string,16,"%d:%d:%d:%d",x, x+1, ymin, ymax);
                                LoadSDF(string);
                        }
        }
 }
 
-int LoadPLI(char *filename)
+int LoadANO(char *filename)
 {
+       /* This function reads a SPLAT! alphanumeric output 
+          file (-ani option) for analysis and/or map generation. */
+
        int     error=0, max_west, min_west, max_north, min_north;
-       char    string[80], *pointer=NULL;
+       char    string[80], *pointer=NULL, *s=NULL;
        double  latitude=0.0, longitude=0.0, azimuth=0.0, elevation=0.0,
-               loss=0.0;
+               ano=0.0;
        FILE    *fd;
 
        fd=fopen(filename,"r");
 
        if (fd!=NULL)
        {
-               fgets(string,78,fd);
+               s=fgets(string,78,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -5080,7 +6908,7 @@ int LoadPLI(char *filename)
 
                sscanf(string,"%d, %d",&max_west, &min_west);
 
-               fgets(string,78,fd);
+               s=fgets(string,78,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -5088,7 +6916,7 @@ int LoadPLI(char *filename)
 
                sscanf(string,"%d, %d",&max_north, &min_north);
 
-               fgets(string,78,fd);
+               s=fgets(string,78,fd);
                pointer=strchr(string,';');
 
                if (pointer!=NULL)
@@ -5099,24 +6927,64 @@ int LoadPLI(char *filename)
                fprintf(stdout,"\nReading \"%s\"... ",filename);
                fflush(stdout);
 
-               fscanf(fd,"%lf, %lf, %lf, %lf, %lf",&latitude, &longitude, &azimuth, &elevation, &loss);
+               s=fgets(string,78,fd);
+               sscanf(string,"%lf, %lf, %lf, %lf, %lf",&latitude, &longitude, &azimuth, &elevation, &ano);
 
                while (feof(fd)==0)
                {
-                       if (loss>225.0)
-                               loss=225.0;
+                       if (LR.erp==0.0)
+                       {
+                               /* Path loss */
+
+                               if (contour_threshold==0 || (fabs(ano)<=(double)contour_threshold))
+                               {
+                                       ano=fabs(ano);
+
+                                       if (ano>255.0)
+                                               ano=255.0;
+
+                                       PutSignal(latitude,longitude,((unsigned char)round(ano)));
+                               }
+                       }
+
+                       if (LR.erp!=0.0 && dbm!=0)
+                       {
+                               /* signal power level in dBm */
 
-                       if (loss<75.0)
-                               loss=75.0;
+                               if (contour_threshold==0 || (ano>=(double)contour_threshold))
+                               {
+                                       ano=200.0+rint(ano);
+
+                                       if (ano<0.0)
+                                               ano=0.0;
+
+                                       if (ano>255.0)
+                                               ano=255.0;
+
+                                       PutSignal(latitude,longitude,((unsigned char)round(ano)));
+                               }
+                       }
+
+                       if (LR.erp!=0.0 && dbm==0)
+                       {
+                               /* field strength dBuV/m */
 
-                       loss-=75.0;
-                       loss/=10.0;
-                       loss+=1.0;
+                               if (contour_threshold==0 || (ano>=(double)contour_threshold))
+                               {
+                                       ano=100.0+rint(ano);
+
+                                       if (ano<0.0)
+                                               ano=0.0;
 
-                       if (loss<=(double)maxdB)
-                               OrMask(latitude,longitude,((unsigned char)(loss))<<3);
+                                       if (ano>255.0)
+                                               ano=255.0;
+
+                                       PutSignal(latitude,longitude,((unsigned char)round(ano)));
+                               }
+                       }
 
-                       fscanf(fd,"%lf, %lf, %lf, %lf, %lf",&latitude, &longitude, &azimuth, &elevation, &loss);
+                       s=fgets(string,78,fd);
+                       sscanf(string,"%lf, %lf, %lf, %lf, %lf",&latitude, &longitude, &azimuth, &elevation, &ano);
                }
 
                fclose(fd);
@@ -5151,7 +7019,7 @@ void WriteKML(struct site source, struct site destination)
 
        fprintf(fd,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        fprintf(fd,"<kml xmlns=\"http://earth.google.com/kml/2.0\">\n");
-       fprintf(fd,"<!-- Generated by SPLAT! Version %s -->\n",splat_version);
+       fprintf(fd,"<!-- Generated by %s Version %s -->\n",splat_name, splat_version);
        fprintf(fd,"<Folder>\n");
        fprintf(fd,"<name>SPLAT! Path</name>\n");
        fprintf(fd,"<open>1</open>\n");
@@ -5211,7 +7079,6 @@ void WriteKML(struct site source, struct site destination)
 
        fprintf(fd,"       <BR>%s West</BR>\n",dec2dms(destination.lon));
 
-
        if (metric)
                fprintf(fd,"       <BR>%.2f km",distance*KM_PER_MILE);
        else
@@ -5309,7 +7176,7 @@ void WriteKML(struct site source, struct site destination)
                           statement is reversed from what it would
                           be if the actual angles were compared. */
 
-                       if (cos_xmtr_angle>cos_test_angle)
+                       if (cos_xmtr_angle>=cos_test_angle)
                                block=1;
                }
 
@@ -5336,7 +7203,7 @@ void WriteKML(struct site source, struct site destination)
 
        fclose(fd);
 
-       fprintf(stdout, "KML file written to: \"%s\"\n",report_name);
+       fprintf(stdout, "\nKML file written to: \"%s\"",report_name);
 
        fflush(stdout);
 }
@@ -5347,87 +7214,135 @@ int main(int argc, char *argv[])
                        rxlat, rxlon, txlat, txlon, west_min, west_max,
                        north_min, north_max;
 
-       unsigned char   coverage=0, LRmap=0, ext[20], terrain_plot=0,
-                       elevation_plot=0, height_plot=0, 
+       unsigned char   coverage=0, LRmap=0, terrain_plot=0,
+                       elevation_plot=0, height_plot=0, map=0,
                        longley_plot=0, cities=0, bfs=0, txsites=0,
-                       count, report='y', norm=0, topomap=0, geo=0,
-                       kml=0;
+                       norm=0, topomap=0, geo=0, kml=0, pt2pt_mode=0,
+                       area_mode=0, max_txsites, ngs=0, nolospath=0,
+                       nositereports=0, fresnel_plot=1;
  
        char            mapfile[255], header[80], city_file[5][255], 
                        elevation_file[255], height_file[255], 
                        longley_file[255], terrain_file[255],
                        string[255], rxfile[255], *env=NULL,
-                       txfile[255], map=0, boundary_file[5][255],
-                       udt_file[255], rxsite=0, plo_filename[255],
-                       pli_filename[255], nf=0;
+                       txfile[255], boundary_file[5][255],
+                       udt_file[255], rxsite=0, ani_filename[255],
+                       ano_filename[255], ext[20], *s=NULL;
 
        double          altitude=0.0, altitudeLR=0.0, tx_range=0.0,
-                       rx_range=0.0, deg_range=0.0, deg_limit,
-                       deg_range_lon, er_mult, freq=0.0;
+                       rx_range=0.0, deg_range=0.0, deg_limit=0.0,
+                       deg_range_lon, er_mult;
 
-       struct          site tx_site[4], rx_site;
+       struct          site tx_site[32], rx_site;
 
        FILE            *fd;
 
+       strncpy(splat_version,"1.3.0\0",6);
+
+       if (HD_MODE==1)
+               strncpy(splat_name,"SPLAT! HD\0",10);
+       else
+               strncpy(splat_name,"SPLAT!\0",7);
+
+       strncpy(dashes,"---------------------------------------------------------------------------\0",76);
 
        if (argc==1)
        {
-               fprintf(stdout,"\n\t\t --==[ SPLAT! v%s Available Options... ]==--\n\n",splat_version);
-               fprintf(stdout,"       -t txsite(s).qth (max of 4)\n");
+               fprintf(stdout,"\n\t\t --==[ %s v%s Available Options... ]==--\n\n",splat_name, splat_version);
+
+               fprintf(stdout,"       -t txsite(s).qth (max of 4 with -c, max of 30 with -L)\n");
                fprintf(stdout,"       -r rxsite.qth\n");
                fprintf(stdout,"       -c plot coverage of TX(s) with an RX antenna at X feet/meters AGL\n");
                fprintf(stdout,"       -L plot path loss map of TX based on an RX at X feet/meters AGL\n");
                fprintf(stdout,"       -s filename(s) of city/site file(s) to import (5 max)\n");
-               fprintf(stdout,"       -b filename(s) of cartographic boundary file(s) to import (max of 5)\n");
+               fprintf(stdout,"       -b filename(s) of cartographic boundary file(s) to import (5 max)\n");
                fprintf(stdout,"       -p filename of terrain profile graph to plot\n");
                fprintf(stdout,"       -e filename of terrain elevation graph to plot\n");
                fprintf(stdout,"       -h filename of terrain height graph to plot\n");
                fprintf(stdout,"       -H filename of normalized terrain height graph to plot\n");
-               fprintf(stdout,"       -l filename of Longley-Rice graph to plot\n");
+               fprintf(stdout,"       -l filename of path loss graph to plot\n");
                fprintf(stdout,"       -o filename of topographic map to generate (.ppm)\n");
                fprintf(stdout,"       -u filename of user-defined terrain file to import\n");
                fprintf(stdout,"       -d sdf file directory path (overrides path in ~/.splat_path file)\n");
-               fprintf(stdout,"       -n no analysis, brief report\n");
-               fprintf(stdout,"       -N no analysis, no report\n");
                fprintf(stdout,"       -m earth radius multiplier\n");
+               fprintf(stdout,"       -n do not plot LOS paths in .ppm maps\n");
+               fprintf(stdout,"       -N do not produce unnecessary site or obstruction reports\n");   
                fprintf(stdout,"       -f frequency for Fresnel zone calculation (MHz)\n");
                fprintf(stdout,"       -R modify default range for -c or -L (miles/kilometers)\n");
-               fprintf(stdout,"      -db maximum loss contour to display on path loss maps (80-230 dB)\n");
+               fprintf(stdout,"      -db threshold beyond which contours will not be displayed\n");
                fprintf(stdout,"      -nf do not plot Fresnel zones in height plots\n");
-               fprintf(stdout,"     -plo filename of path-loss output file\n");
-               fprintf(stdout,"     -pli filename of path-loss input file\n");
-               fprintf(stdout,"     -udt filename of user defined terrain input file\n");
+               fprintf(stdout,"      -fz Fresnel zone clearance percentage (default = 60)\n");
+               fprintf(stdout,"      -gc ground clutter height (feet/meters)\n");
+               fprintf(stdout,"     -ngs display greyscale topography as white in .ppm files\n");      
+               fprintf(stdout,"     -erp override ERP in .lrp file (Watts)\n");
+               fprintf(stdout,"     -ano name of alphanumeric output file\n");
+               fprintf(stdout,"     -ani name of alphanumeric input file\n");
+               fprintf(stdout,"     -udt name of user defined terrain input file\n");
+               fprintf(stdout,"     -kml generate Google Earth (.kml) compatible output\n");
                fprintf(stdout,"     -geo generate an Xastir .geo georeference file (with .ppm output)\n");
-               fprintf(stdout,"     -kml generate a Google Earth .kml file (for point-to-point links)\n");
+               fprintf(stdout,"     -dbm plot signal power level contours rather than field strength\n");
+               fprintf(stdout,"   -gpsav preserve gnuplot temporary working files after SPLAT! execution\n");
                fprintf(stdout,"  -metric employ metric rather than imperial units for all user I/O\n\n");
-
                fprintf(stdout,"If that flew by too fast, consider piping the output through 'less':\n");
-               fprintf(stdout,"\n\tsplat | less\n\n");
+
+               if (HD_MODE==0)
+                       fprintf(stdout,"\n\tsplat | less\n\n");
+               else
+                       fprintf(stdout,"\n\tsplat-hd | less\n\n");
+
                fprintf(stdout,"Type 'man splat', or see the documentation for more details.\n\n");
+
+               y=(int)sqrt((int)MAXPAGES);
+
+               fprintf(stdout,"This compilation of %s supports analysis over a region of\n%d square ",splat_name,y);
+
+               if (y==1)
+
+                       fprintf(stdout,"degree");
+               else
+                       fprintf(stdout,"degrees");
+
+               fprintf(stdout," of terrain.\n\n");
                fflush(stdout);
+
                return 1;
        }
 
        y=argc-1;
 
+       kml=0;
+       geo=0;
+       dbm=0;
+       gpsav=0;
        metric=0;
        rxfile[0]=0;
        txfile[0]=0;
        string[0]=0;
        mapfile[0]=0;
+       clutter=0.0;
+       forced_erp=-1.0;
+       forced_freq=0.0;
        elevation_file[0]=0;
        terrain_file[0]=0;
        sdf_path[0]=0;
        udt_file[0]=0;
        path.length=0;
-       LR.frq_mhz=0.0;
+       max_txsites=30;
+       fzone_clearance=0.6;
+       contour_threshold=0;
        rx_site.lat=91.0;
        rx_site.lon=361.0;
-       plo_filename[0]=0;
-       pli_filename[0]=0;
+       longley_file[0]=0;
+       ano_filename[0]=0;
+       ani_filename[0]=0;
        earthradius=EARTHRADIUS;
 
-       sprintf(header,"\n\t\t--==[ Welcome To SPLAT! v%s ]==--\n\n", splat_version);
+       ippd=IPPD;              /* pixels per degree (integer) */
+       ppd=(double)ippd;       /* pixels per degree (double)  */
+       dpp=1.0/ppd;            /* degrees per pixel */
+       mpi=ippd-1;             /* maximum pixel index per degree */
+
+       sprintf(header,"\n\t\t--==[ Welcome To %s v%s ]==--\n\n", splat_name, splat_version);
 
        for (x=0; x<4; x++)
        {
@@ -5435,7 +7350,7 @@ int main(int argc, char *argv[])
                tx_site[x].lon=361.0;
        }
 
-       for (x=0; x<MAXSLOTS; x++)
+       for (x=0; x<MAXPAGES; x++)
        {
                dem[x].min_el=32768;
                dem[x].max_el=-32768;
@@ -5483,6 +7398,34 @@ int main(int argc, char *argv[])
                        }                        
                }
 
+               if (strcmp(argv[x],"-gc")==0)
+               {
+                       z=x+1;
+
+                       if (z<=y && argv[z][0] && argv[z][0]!='-')
+                       {
+                               sscanf(argv[z],"%lf",&clutter);
+
+                               if (clutter<0.0)
+                                       clutter=0.0;
+                       }                        
+               }
+
+               if (strcmp(argv[x],"-fz")==0)
+               {
+                       z=x+1;
+
+                       if (z<=y && argv[z][0] && argv[z][0]!='-')
+                       {
+                               sscanf(argv[z],"%lf",&fzone_clearance);
+
+                               if (fzone_clearance<0.0 || fzone_clearance>100.0)
+                                       fzone_clearance=60.0;
+
+                               fzone_clearance/=100.0;
+                       }
+               }
+
                if (strcmp(argv[x],"-o")==0)
                {
                        z=x+1;
@@ -5492,7 +7435,7 @@ int main(int argc, char *argv[])
                        map=1;
                }
 
-               if (strcmp(argv[x],"-u")==0)
+               if (strcmp(argv[x],"-udt")==0)
                {
                        z=x+1;
 
@@ -5507,7 +7450,10 @@ int main(int argc, char *argv[])
                        if (z<=y && argv[z][0] && argv[z][0]!='-')
                        {
                                sscanf(argv[z],"%lf",&altitude);
+                               map=1;
                                coverage=1;
+                               area_mode=1;
+                               max_txsites=4;
                        }
                }
 
@@ -5515,18 +7461,8 @@ int main(int argc, char *argv[])
                {
                        z=x+1;
 
-                       if (z<=y && argv[z][0] && argv[z][0]!='-')
-                       {
-                               sscanf(argv[z],"%d",&maxdB);
-
-                               maxdB=abs(maxdB);
-
-                               if (maxdB<80)
-                                       maxdB=80;
-
-                               if (maxdB>230)
-                                       maxdB=230;
-                       }                        
+                       if (z<=y && argv[z][0]) /* A minus argument is legal here */
+                               sscanf(argv[z],"%d",&contour_threshold);
                }
 
                if (strcmp(argv[x],"-p")==0)
@@ -5537,6 +7473,7 @@ int main(int argc, char *argv[])
                        {
                                strncpy(terrain_file,argv[z],253);
                                terrain_plot=1;
+                               pt2pt_mode=1;
                        }
                }
 
@@ -5548,6 +7485,7 @@ int main(int argc, char *argv[])
                        {
                                strncpy(elevation_file,argv[z],253);
                                elevation_plot=1;
+                               pt2pt_mode=1;
                        }
                }
 
@@ -5559,6 +7497,7 @@ int main(int argc, char *argv[])
                        {
                                strncpy(height_file,argv[z],253);
                                height_plot=1;
+                               pt2pt_mode=1;
                        }
 
                        if (strcmp(argv[x],"-H")==0)
@@ -5567,21 +7506,12 @@ int main(int argc, char *argv[])
                                norm=0;
                }
 
-               if (strcmp(argv[x],"-n")==0)
-               {
-                       report='n';
-                       map=1;
-               }
-
-               if (strcmp(argv[x],"-N")==0)
-               {
-                       report='N';
-                       map=1;
-               }
-
                if (strcmp(argv[x],"-metric")==0)
                        metric=1;
 
+               if (strcmp(argv[x],"-gpsav")==0)
+                       gpsav=1;
+
                if (strcmp(argv[x],"-geo")==0)
                        geo=1;
 
@@ -5589,7 +7519,22 @@ int main(int argc, char *argv[])
                        kml=1;
 
                if (strcmp(argv[x],"-nf")==0)
-                       nf=1;
+                       fresnel_plot=0;
+
+               if (strcmp(argv[x],"-ngs")==0)
+                       ngs=1;
+
+               if (strcmp(argv[x],"-n")==0)
+                       nolospath=1;
+
+               if (strcmp(argv[x],"-dbm")==0)
+                       dbm=1;
+
+               if (strcmp(argv[x],"-N")==0)
+               {
+                       nolospath=1;
+                       nositereports=1;
+               }
 
                if (strcmp(argv[x],"-d")==0)
                {
@@ -5605,7 +7550,7 @@ int main(int argc, char *argv[])
 
                        z=x+1;
 
-                       while (z<=y && argv[z][0] && argv[z][0]!='-' && txsites<4)
+                       while (z<=y && argv[z][0] && argv[z][0]!='-' && txsites<30)
                        {
                                strncpy(txfile,argv[z],253);
                                tx_site[txsites]=LoadQTH(txfile);
@@ -5623,14 +7568,12 @@ int main(int argc, char *argv[])
                        if (z<=y && argv[z][0] && argv[z][0]!='-')
                        {
                                sscanf(argv[z],"%lf",&altitudeLR);
+                               map=1;
+                               LRmap=1;
+                               area_mode=1;
 
                                if (coverage)
                                        fprintf(stdout,"c and L are exclusive options, ignoring L.\n");
-                               else
-                               {
-                                       LRmap=1;
-                                       ReadLRParm(txfile);
-                               } 
                        }
                }
 
@@ -5642,8 +7585,7 @@ int main(int argc, char *argv[])
                        {
                                strncpy(longley_file,argv[z],253);
                                longley_plot=1;
-                               /* Doing this twice is harmless */
-                               ReadLRParm(txfile);
+                               pt2pt_mode=1;
                        }
                }
 
@@ -5658,6 +7600,7 @@ int main(int argc, char *argv[])
                                strncpy(rxfile,argv[z],253);
                                rx_site=LoadQTH(rxfile);
                                rxsite=1;
+                               pt2pt_mode=1;
                        }
                }
 
@@ -5699,30 +7642,43 @@ int main(int argc, char *argv[])
 
                        if (z<=y && argv[z][0] && argv[z][0]!='-')
                        {
-                               sscanf(argv[z],"%lf",&freq);
+                               sscanf(argv[z],"%lf",&forced_freq);
+
+                               if (forced_freq<20.0)
+                                       forced_freq=0.0;
+
+                               if (forced_freq>20.0e3)
+                                       forced_freq=20.0e3;
+                       }
+               }
+
+               if (strcmp(argv[x],"-erp")==0)
+               {
+                       z=x+1;
 
-                               if (freq<20)
-                                       freq=20;
+                       if (z<=y && argv[z][0] && argv[z][0]!='-')
+                       {
+                               sscanf(argv[z],"%lf",&forced_erp);
 
-                               if (freq>20e3)
-                                       freq=20e3;
+                               if (forced_erp<0.0)
+                                       forced_erp=-1.0;
                        }                        
                }
 
-               if (strcmp(argv[x],"-plo")==0)
+               if (strcmp(argv[x],"-ano")==0)
                {
                        z=x+1;
 
                        if (z<=y && argv[z][0] && argv[z][0]!='-')
-                               strncpy(plo_filename,argv[z],253);
+                               strncpy(ano_filename,argv[z],253);
                }
 
-               if (strcmp(argv[x],"-pli")==0)
+               if (strcmp(argv[x],"-ani")==0)
                {
                        z=x+1;
 
                        if (z<=y && argv[z][0] && argv[z][0]!='-')
-                               strncpy(pli_filename,argv[z],253);
+                               strncpy(ani_filename,argv[z],253);
                }
        }
 
@@ -5752,7 +7708,7 @@ int main(int argc, char *argv[])
                exit (-1);
        }
 
-       if ((coverage+LRmap+pli_filename[0])==0 && rx_site.lat==91.0 && rx_site.lon==361.0)
+       if ((coverage+LRmap+ani_filename[0])==0 && rx_site.lat==91.0 && rx_site.lon==361.0)
        {
                if (max_range!=0.0 && txsites!=0)
                {
@@ -5760,7 +7716,6 @@ int main(int argc, char *argv[])
 
                        map=0;
                        topomap=1;
-                       report='N';
                }
 
                else
@@ -5779,6 +7734,7 @@ int main(int argc, char *argv[])
                altitudeLR/=METERS_PER_FOOT;    /* meters --> feet */
                max_range/=KM_PER_MILE;         /* kilometers --> miles */
                altitude/=METERS_PER_FOOT;      /* meters --> feet */
+               clutter/=METERS_PER_FOOT;       /* meters --> feet */
        }
 
        /* If no SDF path was specified on the command line (-d), check
@@ -5790,12 +7746,12 @@ int main(int argc, char *argv[])
        if (sdf_path[0]==0)
        {
                env=getenv("HOME");
-               sprintf(string,"%s/.splat_path",env);
+               snprintf(string,253,"%s/.splat_path",env);
                fd=fopen(string,"r");
 
                if (fd!=NULL)
                {
-                       fgets(string,253,fd);
+                       s=fgets(string,253,fd);
 
                        /* Remove <CR> and/or <LF> from string */
 
@@ -5824,11 +7780,12 @@ int main(int argc, char *argv[])
        fprintf(stdout,"%s",header);
        fflush(stdout);
 
-       if (pli_filename[0])
+       if (ani_filename[0])
        {
-               y=LoadPLI(pli_filename);
+               ReadLRParm(tx_site[0],0); /* Get ERP status */
+               y=LoadANO(ani_filename);
 
-               for (x=0; x<txsites; x++)
+               for (x=0; x<txsites && x<max_txsites; x++)
                        PlaceMarker(tx_site[x]);
 
                if (rxsite)
@@ -5838,15 +7795,29 @@ int main(int argc, char *argv[])
                {
                        for (x=0; x<bfs; x++)
                                LoadBoundaries(boundary_file[x]);
+
+                       fprintf(stdout,"\n");
+                       fflush(stdout);
                }
 
                if (cities)
                {
                        for (x=0; x<cities; x++)
                                LoadCities(city_file[x]);
+
+                       fprintf(stdout,"\n");
+                       fflush(stdout);
                }
 
-               WritePPMLR(mapfile,geo);
+               if (LR.erp==0.0)
+                       WritePPMLR(mapfile,geo,kml,ngs,tx_site,txsites);
+               else
+               {
+                       if (dbm)
+                               WritePPMDBM(mapfile,geo,kml,ngs,tx_site,txsites);
+                       else
+                               WritePPMSS(mapfile,geo,kml,ngs,tx_site,txsites);
+               }
 
                exit(0);
        }
@@ -5860,7 +7831,7 @@ int main(int argc, char *argv[])
        min_lon=(int)floor(tx_site[0].lon);
        max_lon=(int)floor(tx_site[0].lon);
 
-       for (y=0, z=0; z<txsites; z++)
+       for (y=0, z=0; z<txsites && z<max_txsites; z++)
        {
                txlat=(int)floor(tx_site[z].lat);
                txlon=(int)floor(tx_site[z].lon);
@@ -5874,7 +7845,7 @@ int main(int argc, char *argv[])
                if (LonDiff(txlon,min_lon)<0.0)
                        min_lon=txlon;
 
-               if (LonDiff(txlon,max_lon)>0.0)
+               if (LonDiff(txlon,max_lon)>=0.0)
                        max_lon=txlon;
        }
 
@@ -5892,7 +7863,7 @@ int main(int argc, char *argv[])
                if (LonDiff(rxlon,min_lon)<0.0)
                        min_lon=rxlon;
 
-               if (LonDiff(rxlon,max_lon)>0.0)
+               if (LonDiff(rxlon,max_lon)>=0.0)
                        max_lon=rxlon;
        }
 
@@ -5900,12 +7871,9 @@ int main(int argc, char *argv[])
 
        LoadTopoData(max_lon, min_lon, max_lat, min_lat);
 
-       if (coverage | LRmap | topomap)
+       if (area_mode || topomap)
        {
-               if (LRmap)
-                       txsites=1;
-
-               for (z=0; z<txsites; z++)
+               for (z=0; z<txsites && z<max_txsites; z++)
                {
                        /* "Ball park" estimates used to load any additional
                           SDF files required to conduct this analysis. */
@@ -5920,28 +7888,30 @@ int main(int argc, char *argv[])
                        /* deg_range determines the maximum
                           amount of topo data we read */
 
-                       deg_range=(tx_range+rx_range)/69.0;
+                       deg_range=(tx_range+rx_range)/57.0;
 
-                       /* max_range sets the maximum size of the
+                       /* max_range regulates the size of the
                           analysis.  A small, non-zero amount can
                           be used to shrink the size of the analysis
                           and limit the amount of topo data read by
-                          SPLAT!  A very large number will only increase
-                          the width of the analysis, not the size of
+                          SPLAT!  A large number will increase the
+                          width of the analysis and the size of
                           the map. */
 
                        if (max_range==0.0)
                                max_range=tx_range+rx_range;
 
-                       if (max_range<(tx_range+rx_range))
-                               deg_range=max_range/69.0;
+                       deg_range=max_range/57.0;
 
                        /* Prevent the demand for a really wide coverage
-                          from allocating more slots than are available
+                          from allocating more "pages" than are available
                           in memory. */
 
-                       switch (MAXSLOTS)
+                       switch (MAXPAGES)
                        {
+                               case 1: deg_limit=0.125;
+                                       break;
+
                                case 2: deg_limit=0.25;
                                        break;
 
@@ -5951,16 +7921,26 @@ int main(int argc, char *argv[])
                                case 9: deg_limit=1.0;
                                        break;
 
-                               case 16: deg_limit=2.0;
+                               case 16: deg_limit=1.5;  /* WAS 2.0 */
+                                       break;
+
+                               case 25: deg_limit=2.0;  /* WAS 3.0 */
+                                       break;
+
+                               case 36: deg_limit=2.5;  /* New! */
+                                       break;
+
+                               case 49: deg_limit=3.0;  /* New! */
                                        break;
 
-                               case 25: deg_limit=3.0;
+                               case 64: deg_limit=3.5;  /* New! */
+                                       break;
                        }
 
-                       if (tx_site[z].lat<70.0)
-                               deg_range_lon=deg_range/cos(deg2rad*tx_site[z].lat);
+                       if (fabs(tx_site[z].lat)<70.0)
+                               deg_range_lon=deg_range/cos(DEG2RAD*tx_site[z].lat);
                        else
-                               deg_range_lon=deg_range/cos(deg2rad*70.0);
+                               deg_range_lon=deg_range/cos(DEG2RAD*70.0);
 
                        /* Correct for squares in degrees not being square in miles */  
 
@@ -5970,7 +7950,6 @@ int main(int argc, char *argv[])
                        if (deg_range_lon>deg_limit)
                                deg_range_lon=deg_limit;
 
-
                        north_min=(int)floor(tx_site[z].lat-deg_range);
                        north_max=(int)floor(tx_site[z].lat+deg_range);
 
@@ -5999,7 +7978,7 @@ int main(int argc, char *argv[])
                        if (LonDiff(west_min,min_lon)<0.0)
                                min_lon=west_min;
 
-                       if (LonDiff(west_max,max_lon)>0.0)
+                       if (LonDiff(west_max,max_lon)>=0.0)
                                max_lon=west_max;
                }
 
@@ -6007,47 +7986,110 @@ int main(int argc, char *argv[])
 
                LoadTopoData(max_lon, min_lon, max_lat, min_lat);
        }
-
+       
        if (udt_file[0])
                LoadUDT(udt_file);
 
-       if (mapfile[0] && topomap==0)
-               map=1;
 
-       if (freq==0.0 && nf==0)
-               freq=LR.frq_mhz;
+       /***** Let the SPLATting begin! *****/
 
-       else if (nf==1)
-               freq=0.0;
-
-       if (coverage | LRmap)
+       if (pt2pt_mode)
        {
-               for (x=0; x<txsites; x++)
+               PlaceMarker(rx_site);
+
+               if (terrain_plot)
                {
-                       if (coverage)
-                               PlotCoverage(tx_site[x],altitude);
+                       /* Extract extension (if present)
+                          from "terrain_file" */
 
-                       if (LRmap)
-                               PlotLRMap(tx_site[x],altitudeLR,plo_filename);
+                       y=strlen(terrain_file);
 
-                       PlaceMarker(tx_site[x]);
+                       for (x=y-1; x>0 && terrain_file[x]!='.'; x--);
 
-                       if (report!='N')
-                               SiteReport(tx_site[x]);
+                       if (x>0)  /* Extension found */
+                       {
+                               for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                                       ext[z-(x+1)]=tolower(terrain_file[z]);
+
+                               ext[z-(x+1)]=0;     /* Ensure an ending 0 */
+                               terrain_file[x]=0;  /* Chop off extension */
+                       }
+
+                       else
+                               strncpy(ext,"png\0",4);
                }
 
-               map=1;
-       }
+               if (elevation_plot)
+               {
+                       /* Extract extension (if present)
+                          from "elevation_file" */
 
-       if (coverage==0 && LRmap==0)       
-       {
-               PlaceMarker(rx_site);
+                       y=strlen(elevation_file);
 
-               for (x=0; x<txsites; x++)
+                       for (x=y-1; x>0 && elevation_file[x]!='.'; x--);
+
+                       if (x>0)  /* Extension found */
+                       {
+                               for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                                       ext[z-(x+1)]=tolower(elevation_file[z]);
+
+                               ext[z-(x+1)]=0;       /* Ensure an ending 0 */
+                               elevation_file[x]=0;  /* Chop off extension */
+                       }
+
+                       else
+                               strncpy(ext,"png\0",4);
+               }
+
+               if (height_plot)
+               {
+                       /* Extract extension (if present)
+                          from "height_file" */
+
+                       y=strlen(height_file);
+
+                       for (x=y-1; x>0 && height_file[x]!='.'; x--);
+
+                       if (x>0)  /* Extension found */
+                       {
+                               for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                                       ext[z-(x+1)]=tolower(height_file[z]);
+
+                               ext[z-(x+1)]=0;    /* Ensure an ending 0 */
+                               height_file[x]=0;  /* Chop off extension */
+                       }
+
+                       else
+                               strncpy(ext,"png\0",4);
+               }
+
+               if (longley_plot)
+               {
+                       /* Extract extension (if present)
+                          from "longley_file" */
+
+                       y=strlen(longley_file);
+
+                       for (x=y-1; x>0 && longley_file[x]!='.'; x--);
+
+                       if (x>0)  /* Extension found */
+                       {
+                               for (z=x+1; z<=y && (z-(x+1))<10; z++)
+                                       ext[z-(x+1)]=tolower(longley_file[z]);
+
+                               ext[z-(x+1)]=0;     /* Ensure an ending 0 */
+                               longley_file[x]=0;  /* Chop off extension */
+                       }
+
+                       else
+                               strncpy(ext,"png\0",4);
+               }
+
+               for (x=0; x<txsites && x<4; x++)
                {
                        PlaceMarker(tx_site[x]);
 
-                       if (report=='y')
+                       if (nolospath==0)
                        {
                                switch (x)
                                {
@@ -6068,166 +8110,129 @@ int main(int argc, char *argv[])
                                }
                        }
 
-                       if (report!='N')
-                               ObstructionReport(tx_site[x],rx_site,report,freq);
+                       if (nositereports==0)
+                               SiteReport(tx_site[x]);
 
                        if (kml)
                                WriteKML(tx_site[x],rx_site);
-               }
-       }
-
-       if (map | topomap)
-       {
-               if (bfs)
-               {
-                       for (x=0; x<bfs; x++)
-                               LoadBoundaries(boundary_file[x]);
-               }
-
-               if (cities)
-               {
-                       for (x=0; x<cities; x++)
-                               LoadCities(city_file[x]);
-               }
 
-               if (LRmap)
-                       WritePPMLR(mapfile,geo);
-               else
-                       WritePPM(mapfile,geo);
-       }
-
-       if (terrain_plot)
-       {
-               if (txsites>1)
-               {
-                       for (x=0; terrain_file[x]!='.' && terrain_file[x]!=0 && x<80; x++);
+                       if (txsites>1)
+                               snprintf(string,250,"%s-%c.%s%c",longley_file,'1'+x,ext,0);
+                       else
+                               snprintf(string,250,"%s.%s%c",longley_file,ext,0);
 
-                       if (terrain_file[x]=='.')  /* extension */
+                       if (nositereports==0)
                        {
-                               ext[0]='.';
-                               for (y=1, z=x, x++; terrain_file[x]!=0 && x<253 && y<14; x++, y++)
-                                       ext[y]=terrain_file[x];
+                               if (longley_file[0]==0)
+                               {
+                                       ReadLRParm(tx_site[x],0);
+                                       PathReport(tx_site[x],rx_site,string,0);
+                               }
 
-                               ext[y]=0;
-                               terrain_file[z]=0;
+                               else
+                               {
+                                       ReadLRParm(tx_site[x],1);
+                                       PathReport(tx_site[x],rx_site,string,longley_file[0]);
+                               }
                        }
 
-                       else
+                       if (terrain_plot)
                        {
-                               ext[0]=0;  /* No extension */
-                               terrain_file[x]=0;
-                       }
+                               if (txsites>1)
+                                       snprintf(string,250,"%s-%c.%s%c",terrain_file,'1'+x,ext,0);
+                               else
+                                       snprintf(string,250,"%s.%s%c",terrain_file,ext,0);
 
-                       for (count=0; count<txsites; count++)
-                       {
-                               sprintf(string,"%s-%c%s%c",terrain_file,'1'+count,ext,0);
-                               GraphTerrain(tx_site[count],rx_site,string);
+                               GraphTerrain(tx_site[x],rx_site,string);
                        }
-               }
-
-               else
-                       GraphTerrain(tx_site[0],rx_site,terrain_file);
-       }
-
-       if (elevation_plot)
-       {
-               if (txsites>1)
-               {
-                       for (x=0; elevation_file[x]!='.' && elevation_file[x]!=0 && x<80; x++);
 
-                       if (elevation_file[x]=='.')  /* extension */
+                       if (elevation_plot)
                        {
-                               ext[0]='.';
-                               for (y=1, z=x, x++; elevation_file[x]!=0 && x<253 && y<14; x++, y++)
-                                       ext[y]=elevation_file[x];
+                               if (txsites>1)
+                                       snprintf(string,250,"%s-%c.%s%c",elevation_file,'1'+x,ext,0);
+                               else
+                                       snprintf(string,250,"%s.%s%c",elevation_file,ext,0);
 
-                               ext[y]=0;
-                               elevation_file[z]=0;
+                               GraphElevation(tx_site[x],rx_site,string);
                        }
 
-                       else
+                       if (height_plot)
                        {
-                               ext[0]=0;  /* No extension */
-                               elevation_file[x]=0;
-                       }
+                               if (txsites>1)
+                                       snprintf(string,250,"%s-%c.%s%c",height_file,'1'+x,ext,0);
+                               else
+                                       snprintf(string,250,"%s.%s%c",height_file,ext,0);
 
-                       for (count=0; count<txsites; count++)
-                       {
-                               sprintf(string,"%s-%c%s%c",elevation_file,'1'+count,ext,0);
-                               GraphElevation(tx_site[count],rx_site,string);
+                               GraphHeight(tx_site[x],rx_site,string,fresnel_plot,norm);
                        }
                }
-
-               else
-                       GraphElevation(tx_site[0],rx_site,elevation_file);
        }
 
-       if (height_plot)
+       if (area_mode && topomap==0)
        {
-               if (txsites>1)
+               for (x=0; x<txsites && x<max_txsites; x++)
                {
-                       for (x=0; height_file[x]!='.' && height_file[x]!=0 && x<80; x++);
+                       if (coverage)
+                               PlotLOSMap(tx_site[x],altitude);
 
-                       if (height_file[x]=='.')  /* extension */
-                       {
-                               ext[0]='.';
-                               for (y=1, z=x, x++; height_file[x]!=0 && x<253 && y<14; x++, y++)
-                                       ext[y]=height_file[x];
+                       else if (ReadLRParm(tx_site[x],1))
+                                       PlotLRMap(tx_site[x],altitudeLR,ano_filename);
 
-                               ext[y]=0;
-                               height_file[z]=0;
-                       }
+                       SiteReport(tx_site[x]);
+               }
+       }
 
-                       else
-                       {
-                               ext[0]=0;  /* No extension */
-                               height_file[x]=0;
-                       }
+       if (map || topomap)
+       {
+               /* Label the map */
 
-                       for (count=0; count<txsites; count++)
-                       {
-                               sprintf(string,"%s-%c%s%c",height_file,'1'+count,ext,0);
-                               GraphHeight(tx_site[count],rx_site,string,freq,norm);
-                       }
+               if (kml==0)
+               {
+                       for (x=0; x<txsites && x<max_txsites; x++)
+                               PlaceMarker(tx_site[x]);
                }
 
-               else
-                       GraphHeight(tx_site[0],rx_site,height_file,freq,norm);
-       }
-       
-       if (longley_plot)
-       {
-               if (txsites>1)
+               if (cities)
                {
-                       for (x=0; longley_file[x]!='.' && longley_file[x]!=0 && x<80; x++);
 
-                       if (longley_file[x]=='.')  /* extension */
-                       {
-                               ext[0]='.';
-                               for (y=1, z=x, x++; longley_file[x]!=0 && x<253 && y<14; x++, y++)
-                                       ext[y]=longley_file[x];
+                       for (y=0; y<cities; y++)
+                               LoadCities(city_file[y]);
 
-                               ext[y]=0;
-                               longley_file[z]=0;
-                       }
+                       fprintf(stdout,"\n");
+                       fflush(stdout);
+               }
 
-                       else
-                       {
-                               ext[0]=0;  /* No extension */
-                               longley_file[x]=0;
-                       }
+               /* Load city and county boundary data files */
 
-                       for (count=0; count<txsites; count++)
-                       {
-                               sprintf(string,"%s-%c%s%c",longley_file,'1'+count,ext,0);
-                               GraphLongley(tx_site[count],rx_site,string);
-                       }
+               if (bfs)
+               {
+                       for (y=0; y<bfs; y++)
+                               LoadBoundaries(boundary_file[y]);
+
+                       fprintf(stdout,"\n");
+                       fflush(stdout);
                }
 
+               /* Plot the map */
+
+               if (coverage || pt2pt_mode || topomap)
+                       WritePPM(mapfile,geo,kml,ngs,tx_site,txsites);
+
                else
-                       GraphLongley(tx_site[0],rx_site,longley_file);
+               {
+                       if (LR.erp==0.0)
+                               WritePPMLR(mapfile,geo,kml,ngs,tx_site,txsites);
+                       else
+                               if (dbm)
+                                       WritePPMDBM(mapfile,geo,kml,ngs,tx_site,txsites);
+                               else
+                                       WritePPMSS(mapfile,geo,kml,ngs,tx_site,txsites);
+               }
        }
 
+       printf("\n");
+
+       /* That's all, folks! */
+
        return 0;
 }
-