+ 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)
+ {
+ 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);
+ fprintf(stdout,"Done!\n");
+ fflush(stdout);
+}
+
+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;