* ZipDist.prg
#Define cdbl
#Define _PI 3.1415926535893
#Define _StatuteMile 5280 &&' 5280 feet = 1 statute mile
#Define _NauticalMile 6076.11549 &&' 6076.11549 feet = 1 nautical mile
#Define _Seconds 60 && ' 60 seconds = 1 nautical mile
#Define KMRAD 6377
#Define MIRAD 3963
#Define Radians Dtor
mkDbf() && Create dbf's from the .csv
PlotDots() && puts dots on the desktop in the shape of the US
SnagWindow( _Screen.HWnd, "ZipMap.bmp" ) && makes a file
ZipRadius( "60714", 15 ) && get all zips within 15 miles of 60714
Browse && view the results
Return
Function SnagWindow(tHWnd, tcFileName)
* creates an image file from a Windows window.
Set Path To D:\foxbin\bmpstuff\bmp4
Set Library To Home(0) + "FoxTools.FLL" Additive
Set Classlib To scrnprnt.vcx Additive
oCap = Createobject("CaptureScreen")
lnRetVal = oCap.CaptureWindow( tHWnd, tcFileName)
Return
EndFunc
Function PlotDots()
Local ;
loForm, ;
lnX, lnY
Select ;
Min( latitude ) As MinLat, ;
Min(longitude) As MinLon, ;
Max( latitude ) As MaxLat, ;
Max(longitude) As MaxLon ;
from latlon ;
into Cursor qMinMax
Select State, ;
latitude, longitude ;
from latlon join zipcode on latlon.zipcode = zipcode.zipcode;
order By zipcode.zipcode ;
into Cursor qLatLon
loForm = _Screen
Scan
lnX = (qLatLon.longitude - qMinMax.MinLon) / ((qMinMax.MaxLon-qMinMax.MinLon)/loForm.Width)
lnY = (qLatLon.latitude - qMinMax.MinLat) / ((qMinMax.MaxLat-qMinMax.MinLat)/loForm.Height)
lnCollor = ((Asc(Substr(State,2,1))-65)*26+Asc(Substr(State,1,1))-65) /(26^2)
loForm.ForeColor = lnCollor*256^3
loForm.PSet( lnX*.98, (loForm.Height-lnY)*.98 )
Endscan
Return
Endfunc
Function mkDbf()
* Clean up previous runs
Close Tables All
Erase latlon.Dbf
Erase ZipPop.Dbf
Erase zipcode.dbf
Create Table zipcode (;
zipcode Char(5), ;
CITY Varchar(100), ;
State Char(2) , ;
VCODE Char(2) )
Append From zipcode.Csv Type Csv
Index on zipcode tag zipcode
* Create Table ZipPop ( ;
State Char(2), ;
zipcode Char(5), ;
MystryData Char(59), ;
Population N(9), ;
Housing N(9), ;
LandAreaMe N(14), ;
WatAreaMe N(14), ;
LandAreaMi N(12,6), ;
WatAreaMi N(12,6), ;
latitude N(10,6), ;
longitude N(10,6) )
* Append From zcta5.txt Type Sdf
Create Table latlon ( ;
zipcode Varchar(10), ;
latitude Float(12,7), ;
longitude Float(12,7) )
Append From latlon.Csv Type Csv
Index On zipcode Tag zipcode
Index On latitude Tag latitude
Index On longitude Tag longitude
Return
Endfunc
Func ZipRadius( tcZipcode, tnRadius )
* Select Zipcodes that are w/in X miles of a given zipcode
Local ;
loZip, ;
lnResults, ;
lnCenterLat, lnCenterLon, ;
lnLatRange, lnLonRange, ;
lnLowLat, lnLowLon, lnHighLat, lnHighLon
loZip = ZipToLatLong( tcZipcode )
lnCenterLat = loZip.latitude
lnCenterLon = loZip.longitude
*' 1 degree of latitude = 60 nautical miles or 1 minute = 1 nautical mile
lnLatRange = tnRadius / ((_NauticalMile / _StatuteMile) * _Seconds )
*' 1 degree of longitude at the equator = 60 nautical miles,
*' AT the poles 1 DEGREE = 0 nautical miles.
lnLonRange = tnRadius / (((Cos(cdbl(lnCenterLat * _PI / 180)) * ;
_NauticalMile) / _StatuteMile) * _Seconds)
lnLowLat = lnCenterLat - lnLatRange
lnHighLat = lnCenterLat + lnLatRange
lnLowLon = lnCenterLon - lnLonRange
lnHighLon = lnCenterLon + lnLonRange
* Then use a SQL statement to select all locations within the tnRadius mile RANGE
Select *, ;
ZipDistance( tcZipcode, zipcode, .F. ) As distance ;
FROM latlon ;
WHERE latitude <= lnHighLat ;
AND latitude >= lnLowLat ;
AND longitude >= lnLowLon ;
AND longitude <= lnHighLon ;
HAVING distance <= tnRadius ;
Order By distance ;
INTO Cursor ZipRadius
Return
Endfunc
Func ZipDistance( tcZip1, tcZip2, tlKM )
* Calculate the distance between two zipcodes
* tlKM: true = Killometers, false = Miles
Local ;
loZip1, loZip2, ;
lnDistance, ;
ln1Lat, ln1Lon, ln2Lat, ln2Lon
loZip1 = ZipToLatLong( tcZip1 )
loZip2 = ZipToLatLong( tcZip2 )
lnDistance=Iif(tlKM, KMRAD, MIRAD)*;
ACOS(Cos(Radians(90-loZip1.latitude))*Cos(Radians(90-loZip2.latitude))+;
SIN(Radians(90-loZip1.latitude))*Sin(Radians(90-loZip2.latitude))*;
COS(Radians(loZip1.longitude - loZip2.longitude)))
Return lnDistance
Endfunc
Function ZipToLatLong( tcZip )
* given a zip,
* returns an object with .latitude and .longitude
Local ;
loLatLon
Select latitude, longitude ;
from latlon;
where zipcode == tcZip ;
into Cursor qLatLon
Scatter Name loLatLon
Return loLatLon
Endfunc