+ 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");
+
+ fclose(fd);
+
+ x=system("gnuplot splat.gp");
+
+ if (x!=-1)
+ {
+ unlink("splat.gp");
+ unlink("profile.gp");
+ unlink("reference.gp");
+ unlink("curvature.gp");
+
+ if (f)
+ {
+ unlink("fresnel.gp");
+ unlink("fresnel_pt_6.gp");
+ }
+
+ fprintf(stdout,"\nHeight plot written to: \"%s.%s\"",filename,ext);
+ fflush(stdout);
+ }
+
+ else
+ fprintf(stderr,"\n*** ERROR: Error occurred invoking gnuplot!\n");
+}
+
+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 (f)
+ lambda=9.8425e8/(f*1e6);
+
+ /* 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.
+
+ 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. */
+
+ for (x=path.length-1; x>0; x--)
+ {
+ site_x.lat=path.lat[x];
+ site_x.lon=path.lon[x];
+ site_x.alt=0.0;
+
+ h_x=GetElevation(site_x)+earthradius;
+ d_x=5280.0*Distance(rcvr,site_x);
+
+ /* Deal with the LOS path first. */
+
+ cos_test_angle=((h_r*h_r)+(d_x*d_x)-(h_x*h_x))/(2.0*h_r*d_x);
+
+ if (cos_tx_angle>cos_test_angle)
+ {
+ if (h_r==h_r_orig)
+ fprintf(outfile,"Between %s and %s, SPLAT! detected obstructions at:\n\n",rcvr.name,xmtr.name);
+
+ if (site_x.lat>=0.0)
+ {
+ if (metric)
+ fprintf(outfile,"\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(outfile,"\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);
+ }
+
+ else
+ {
+ if (metric)
+ fprintf(outfile,"\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
+
+ fprintf(outfile,"\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);
+ }
+ }
+
+ 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);
+ }
+
+ if (f)
+ {
+ /* Now clear the first Fresnel zone... */
+
+ 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);
+
+ 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);
+ }
+
+ /* and clear the 60% F1 zone. */
+
+ 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);
+
+ 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)
+ 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);
+ }
+
+ else
+ sprintf(string,"\nNo obstructions to LOS path due to terrain were detected by SPLAT!\n");
+
+ if (f)
+ {
+ 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 %.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
+ sprintf(string_fpt6,"\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);
+ }
+
+ else
+ sprintf(string_fpt6,"\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)
+ 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));
+
+ 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);
+
+ }
+
+ else
+ sprintf(string_f1,"\nThe first Fresnel zone is clear.\n\n");
+ }
+
+ fprintf(outfile,"%s",string);
+
+ if (f)
+ {
+ fprintf(outfile,"%s",string_f1);
+ fprintf(outfile,"%s",string_fpt6);
+ }
+}
+
+void PathReport(struct site source, struct site destination, char *name, char graph_it)
+{
+ /* 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 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, field_strength,
+ free_space_loss=0.0, voltage;
+ FILE *fd=NULL, *fd2=NULL;
+
+ sprintf(report_name,"%s-to-%s.txt",source.name,destination.name);
+
+ four_thirds_earth=EARTHRADIUS*(4.0/3.0);
+
+ for (x=0; report_name[x]!=0; x++)