<?php

function sendGetPage () {
  
//too many ' and " in heredoc?
  
$serverNamePhpSelf = $_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  
$matchtype = $_POST['matchtype'];
  
$cityname = $_POST['cityname'];
  
$latitude = isset($_POST['latitude']) ? $_POST['latitude'] : 0;
  
$longitude = isset($_POST['longitude']) ? $_POST['longitude'] : 0;
  
$bbN = isset($_POST['bbN']) ?  $_POST['bbN'] : 5;
  
$bbS = isset($_POST['bbS']) ?  $_POST['bbS'] : 5;
  
$bbE = isset($_POST['bbE']) ?  $_POST['bbE'] : 5;
  
$bbW = isset($_POST['bbW']) ?  $_POST['bbW'] : 5;
  
$latlongtype = $_POST['latlongtype'];

  if (!isset(
$latlongtype) || $latlongtype=="both")
    
$latlongtypeBothchecked = "checked";
  else if (
$latlongtype == "latitude")
    
$latlongtypeLatchecked = "checked";
  else if (
$latlongtype == "longitude")
    
$latlongtypeLongchecked = "checked";


echo <<< endOfGetPage
<html>
<head>
<title>PHP city latitude longitude</title>
</head>
<body>
<form name="userForm"
action="http://$serverNamePhpSelf";
method="post">
City name
<input type="text" size="20" maxlength="30"  name="cityname" value="$cityname">
&nbsp;&nbsp;&nbsp;&nbsp;
Match type
<input name="matchtype" value="exact" type="radio" checked>Exact
<input name="matchtype" value="substring" type="radio" >Substring
<hr>
  Latitude (-90 to 90)
<input type="text" size="4" maxlength="7"  name="latitude" value="$latitude">
  Longitude (-180 to 180)
<input type="text" size="4" maxlength="7"  name="longitude" value="$longitude">
<br>
  Bounding rectangle degrees from latitude and longitude:
&nbsp;&nbsp;&nbsp;&nbsp;
N<input type="text" size="2" maxlength="3"  name="bbN" value="$bbN">
S<input type="text" size="2" maxlength="3"  name="bbS" value="$bbS">
E<input type="text" size="2" maxlength="3"  name="bbE" value="$bbE">
W<input type="text" size="2" maxlength="3"  name="bbW" value="$bbW">
&nbsp;&nbsp;&nbsp;&nbsp;
Constrain by:
<input name="latlongtype" value="latitude" type="radio" $latlongtypeLatchecked>Latitude
<input name="latlongtype" value="longitude" type="radio" $latlongtypeLongchecked>Longitude
<input name="latlongtype" value="both" type="radio" $latlongtypeBothchecked>Both
<p>
<input value="Find" type="submit">
</form>

endOfGetPage;
}
########################################################

//initial page load.  display form
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
  
bail("");   //no error
}

//one-shot call to add all cities to earth3.jpg, creating earthcity.jpg
/*
$earthcity = getEarthCity();
$datacount = 0;
foreach (explode("\n", $earthcity) as $city) {
  @list($d['lat'],$d['long'],$d['city'],$d['tz'],$poundsign,$d['country'],$comment) =
    preg_split("/\s+/", $city);
  $d['city'] = trim($d['city'], '"');
  $data[$datacount++] = $d;
}
$im = ImageCreateFromJPEG("earth3.jpg");
$w = ImageSx($im);
$midW = $w / 2;
$degreeLong = $w / 360;
$h = ImageSy($im);
$midH = $h / 2;
$degreeLat = $h / 180;
$colorred = ImageColorAllocate($im, 255, 0, 0);

foreach ($data as $city) {
  $latitude = $city['lat'];
  $longitude = $city['long'];

  $x1 = $midW + $longitude * $degreeLong;
  $y1 = $midH - $latitude * $degreeLat;

  ImageFilledRectangle($im, $x1, $y1, $x1+2, $y1+2, $colorred);
}

$colorgray = ImageColorResolveAlpha($im, 70, 70, 70, 100);
ImageAlphaBlending($im, true);

for ($latline=-80; $latline<=80; $latline+=10) {
  $y1 = $midH - $latline * $degreeLat;
  ImageLine($im, 0, $y1, $w, $y1, $colorgray);
}
$colorred = ImageColorResolveAlpha($im, 255, 0, 0, 100);
ImageLine($im, 0, $midH, $w, $midH, $colorred);  //equator
//$colorcyan = ImageColorResolveAlpha($im, 200, 200, 0, 100);
ImageLine($im, 0, $midH-23.5*$degreeLat, $w, $midH-23.5*$degreeLat, $colorred);//cancer
ImageLine($im, 0, $midH+23.5*$degreeLat, $w, $midH+23.5*$degreeLat, $colorred);//capricorn
ImageLine($im, 0, $midH-67.5*$degreeLat, $w, $midH-67.5*$degreeLat, $colorred);//arctic
ImageLine($im, 0, $midH+67.5*$degreeLat, $w, $midH+67.5*$degreeLat, $colorred);//antarctic
//ImageDashedLine  doesn't work???

for ($longline=-180; $longline<=180; $longline+=10) {
  $x1 = $midW + $longline * $degreeLong;
  ImageLine($im, $x1, 0, $x1, $h, $colorgray);
}

ImageJPEG($im,"earthcity.jpg");
echo "<hr>\n<img src=\"earthcity.jpg\">\n";
exit();
*/
//#######################################


$matchtype = $_POST['matchtype'];
$cityname = $_POST['cityname'];
$latitude = $_POST['latitude'];
$longitude = $_POST['longitude'];
$bbN = $_POST['bbN'];
$bbS = $_POST['bbS'];
$bbE = $_POST['bbE'];
$bbW = $_POST['bbW'];
$latlongtype = $_POST['latlongtype'];
//test
/*
$latitude = 40;
$longitude = 40;
//$cityname = "tokyo";
$matchtype = "exact";
$bbN = 5;
$bbS = 5;
$bbE = 5;
$bbW = 5;
$latlongtype = "latitude";
*/


$latlonglookup = false;

if (
$latitude!="" || $longitude!="") {
  if (!
is_numeric($latitude) || !is_numeric($longitude))
    
bail( "<b>Missing or non-numeric data</b>: latitude: $latitude longitude: $longitude \n");

  else if (
$latitude>90 || $latitude<-90 || $longitude>180 || $longitude<-180)
    
bail( "<b>Out of range</b>: latitude: $latitude longitude: $longitude \n");
  
  else if (!
is_numeric($bbN) || !is_numeric($bbS) || !is_numeric($bbE) ||!is_numeric($bbW))
    
bail( "<b>Missing or non-numeric bounding rectangle data</b>");
  else if (
$bbN<0 || $bbS<0 || $bbE<0 || $bbW<0)
    
bail ("<b>Bounding rectangle data must be >= 0</b>\n");
  else if (
$bbN+$latitude>90 || $latitude-$bbS<-90 || $bbE+$bbW>360)
    
bail("<b>bounding rectangle can't go past poles or overlap in longitude</b>\n");
  else
    
$latlonglookup = true;
}


sendGetPage();


$earthcity = getEarthCity();

$datacount = 0;

foreach (
explode("\n", $earthcity) as $city) {
  @list(
$d['lat'],$d['long'],$d['city'],$d['tz'],$poundsign,$d['country'],$comment) =
    
preg_split("/\s+/", $city);
  
$d['city'] = trim($d['city'], '"');
  
$data[$datacount++] = $d;
}

/*
foreach ($data as $city) {
  reset($city);
  while (list($k,$v) = each($city))
    echo "$k: $v, ";
  echo "\n";
}
*/

if ($cityname != "") {
  
$cityname = strtolower($cityname);
  
$cityfound = false;
  echo
"<hr>\n";
  if (
$matchtype == "exact") {
    foreach (
$data as $city) {
      if (
strtolower($city['city']) == $cityname) {
    echo
$city['city']." ".$city['lat']." ".$city['long']."<br>\n";
    
$cityfound = true;
    break;
      }
    }
    if (!
$cityfound)
      echo
"No such city\n";
  }
  else {   
//"substring"
    
foreach ($data as $city) {
      if (
stristr($city['city'], $cityname)) {
    echo
$city['city']." ".$city['lat']." ".$city['long']."<br>\n";
    
$cityfound = true;
      }
    }
    if (!
$cityfound)
      echo
"No such city\n";
  }
}

if (
$latlonglookup) {
  echo
"<hr>\n";
  
$lowerLat = $latitude - $bbS;
  
$upperLat = $latitude + $bbN;
  if (
$lowerLat < -90)
    
$lowerLat = -90;
  if (
$upperLat > 90)
    
$upperLat = 90;

  
$lowerLong = $longitude - $bbW;
  
$upperLong = $longitude + $bbE;
  
//wrap-around longitude
  
$leftwrap = $rightwrap = false;
  if (
$lowerLong < -180) {
    
$lowerLong = 180 - (-180 - $lowerLong);
    
$leftwrap = true;
  }
  if (
$upperLong > 180) {
    
$upperLong = -180 + ($upperLong - 180);
    
$rightwrap = true;
  }

  
$im = ImageCreateFromJPEG("earthcity.jpg");
  
$w = ImageSx($im);
  
$midW = $w / 2;
  
$degreeLong = $w / 360;
  
$h = ImageSy($im);
  
$midH = $h / 2;
  
$degreeLat = $h / 180;
  
//$color = ImageColorAllocate($im, 255, 0, 0);

  
$colorgray = ImageColorResolveAlpha($im, 70, 70, 70, 63);
  
ImageAlphaBlending($im, true);

  if (
$latlongtype == "latitude") {  
    echo
"Latitude:<br>\n";
    foreach (
$data as $city) {
      if (
$city['lat']<=$upperLat && $city['lat']>=$lowerLat)
    echo
$city['city']."  ".$city['lat']." ".$city['long']."<br>\n";
    }
    
$y1 = $midH - $upperLat * $degreeLat;
    
$y2 = $y1 + ($upperLat - $lowerLat) * $degreeLat;
    
ImageFilledRectangle($im, 0, $y1, $w, $y2, $colorgray);
  }
  else if (
$latlongtype == "longitude") {  
    echo
"Longitude:<br>\n";
    foreach (
$data as $city) {
      if ((!
$leftwrap && !$rightwrap &&
       
$city['long']>=$lowerLong && $city['long']<=$upperLong) ||
      ((
$leftwrap || $rightwrap) &&
       (
$city['long']>=$lowerLong || $city['long']<=$upperLong)))
    
    echo
$city['city']."  ".$city['lat']." ".$city['long']."<br>\n";
    }
    if (!
$leftwrap && !$rightwrap) {
      
$x1 = $midW + $lowerLong * $degreeLong;
      
$x2 = $x1 + ($upperLong - $lowerLong) * $degreeLong;
      
ImageFilledRectangle($im, $x1, 0, $x2, $h, $colorgray);
    }
    else {
      
$x2 = ($upperLong + 180) * $degreeLong;
      
ImageFilledRectangle($im, 0, 0, $x2, $h, $colorgray);
      
$x1 = $midW + $lowerLong * $degreeLong;
      
ImageFilledRectangle($im, $x1, 0, $w, $h, $colorgray);
    }
  }
  else {
    echo
"Both:<br>\n";
    foreach (
$data as $city) {
      if (((!
$leftwrap && !$rightwrap &&
        
$city['long']>=$lowerLong && $city['long']<=$upperLong) ||
       ((
$leftwrap || $rightwrap) &&
        (
$city['long']>=$lowerLong || $city['long']<=$upperLong))) &&
      
$city['lat']<=$upperLat && $city['lat']>=$lowerLat)
    echo
$city['city']."  ".$city['lat']." ".$city['long']."<br>\n";
    }
    
$y1 = $midH - $upperLat * $degreeLat;
    
$y2 = $y1 + ($upperLat - $lowerLat) * $degreeLat;
    if (!
$leftwrap && !$rightwrap) {
      
$x1 = $midW + $lowerLong * $degreeLong;
      
$x2 = $x1 + ($upperLong - $lowerLong) * $degreeLong;
      
ImageFilledRectangle($im, $x1, $y1, $x2, $y2, $colorgray);
    }
    else {
      
$x2 = ($upperLong + 180) * $degreeLong;
      
ImageFilledRectangle($im, 0, $y1, $x2, $y2, $colorgray);
      
$x1 = $midW + $lowerLong * $degreeLong;
      
ImageFilledRectangle($im, $x1, $y1, $w, $y2, $colorgray);
    }
  }
  
ImageJPEG($im,"earthcityBand.jpg");
  echo
"<hr>\n<img src=\"earthcityBand.jpg\">\n";
}


echo
"</body>\n</html>";
exit();


function
bail ($message) {
  echo
$message;
  
sendGetPage();
  echo
"<hr>\n<img src=\"earthcity.jpg\">\n";
  echo
"</body>\n</html>";
  exit();
}



#   http://www.getty.edu/research/conducting_research/vocabularies/tgn/about.html

//data from Xplanet marker file

function getEarthCity() {
  
$earthcity = <<<ENDOFEARTHCITY
90.00    0.00 "NorthPole"            timezone=NA/NA                # NorthPole
-90.00    0.00 "SouthPole"            timezone=NA/NA                # SouthPole
12.97   77.58 "Bangalore"             timezone=Asia/Calcutta         # India           (43)
13.73  100.50 "Bangkok"               timezone=Asia/Bangkok          # Thailand        (33)
39.92  116.43 "Beijing"               timezone=Asia/Shanghai         # China           (25)
4.63  -74.08 "Bogotá"                timezone=America/Bogota        # Colombia        (26)
42.35  -71.05 "Boston"                timezone=US/Eastern            # USA             (42)
-34.67  -58.50 "BuenosAires"          timezone=America/Buenos_Aires  # Argentina       (11)
30.05   31.25 "Cairo"                 timezone=Africa/Cairo          # Egypt           ( 9)
22.50   88.33 "Calcutta"              timezone=Asia/Calcutta         # India           (12)
13.08   80.30 "Chennai"               timezone=Asia/Calcutta         # India           (37)
41.85  -87.65 "Chicago"               timezone=America/Chicago       # USA             (24)
30.65  103.68 "Chongqing"             timezone=Asia/Chongqing        # China           (35)
32.78  -96.80 "Dallas"                timezone=America/Chicago       # USA             (47)
28.67   77.22 "Delhi"                 timezone=Asia/Calcutta         # India           (14)
42.32  -83.03 "Detroit"               timezone=America/Detroit       # USA             (44)
23.72   90.37 "Dhaka"                 timezone=Asia/Dhaka            # Bangladesh      (22)
51.45    6.95 "Essen"                 timezone=Europe/Berlin         # Germany         (40)
22.28  114.15 "HongKong"             timezone=Asia/Hongkong         # China           (34)
17.37   78.43 "Hyderabad"             timezone=Asia/Calcutta         # India           (45)
41.03   28.95 "Istanbul"              timezone=Asia/Istanbul         # Turkey          (20)
-6.13  106.75 "Jakarta"               timezone=Asia/Jakarta          # Indonesia       (10)
-26.17   28.03 "Johannesburg"          timezone=Africa/Johannesburg   # SouthAfrica    (36)
24.85   67.03 "Karachi"               timezone=Asia/Karachi          # Pakistan        (19)
15.55   32.53 "Khartoum"              timezone=Africa/Khartoum       # Sudan           (30)
-4.30   15.30 "Kinshasa"              timezone=Africa/Kinshasa       # Congo           (39)
6.45    3.47 "Lagos"                 timezone=Africa/Lagos          # Nigeria         (31)
31.57   74.37 "Lahore"                timezone=Asia/Karachi          # Pakistan        (41)
-12.05  -77.05 "Lima"                  timezone=America/Lima          # Peru            (28)
51.50   -0.17 "London"                timezone=Europe/London         # UnitedKingdom  (17)
34.05 -118.23 "LosAngeles"           timezone=US/Pacific            # USA             ( 7)
14.62  120.97 "Manila"                timezone=Asia/Manila           # Philippines     (15)
19.40  -99.15 "MexicoCity"           timezone=America/Mexico_City   # Mexico          ( 4)
55.75   37.70 "Moscow"                timezone=Europe/Moscow         # Russia          (13)
18.93   72.85 "Mumbai"                timezone=Asia/Calcutta         # India           ( 8)
40.70  -74.00 "NewYork"             timezone=US/Eastern            # USA             ( 2)
34.67  135.50 "Osaka"                 timezone=Asia/Tokyo            # Japan           ( 6)
48.87    2.33 "Paris"                 timezone=Europe/Paris          # France          (23)
39.95  -75.15 "Philadelphia"          timezone=US/Eastern            # USA             (38)
-22.88  -43.28 "RiodeJaneiro"        timezone=America/Sao_Paulo     # Brazil          (18)
37.77 -122.42 "SanFrancisco"         timezone=America/Los_Angeles   # USA             (32)
-33.45  -70.67 "Santiago"              timezone=Chile/Continental     # Chile           (49)
-23.55  -46.65 "SãoPaulo"             timezone=America/Sao_Paulo     # Brazil          ( 5)
37.53  127.00 "Seoul"                 timezone=Asia/Seoul            # SouthKorea     ( 3)
31.10  121.37 "Shanghai"              timezone=Asia/Shanghai         # China           (16)
59.88   30.25 "St.Petersburg"        timezone=Europe/Moscow         # Russia          (46)
25.02  121.37 "Taipei"                timezone=Asia/Taipei           # Taiwan          (29)
35.67   51.43 "Teheran"               timezone=Asia/Tehran           # Iran            (21)
39.13  117.20 "Tianjin"               timezone=Asia/Shanghai         # China           (48)
35.75  139.50 "Tokyo"                 timezone=Asia/Tokyo            # Japan           ( 1)
43.70  -79.42 "Toronto"               timezone=America/Montreal      # Canada          (50)
38.88  -77.03 "Washington"            timezone=US/Eastern          # USA             (27)
23.05   72.67 "Ahmadabad"            timezone=Asia/Calcutta         # India
31.20   29.90 "Alexandria"           timezone=Africa/Cairo          # Egypt
39.92   32.83 "Ankara"               timezone=Asia/Istanbul         # Turkey
33.35   44.42 "Baghdad"              timezone=Asia/Baghdad          # Iraq
52.53   13.42 "Berlin"               timezone=Europe/Berlin         # Germany
10.50  -66.92 "Caracas"              timezone=America/Caracas       # Venezuela
30.62  104.10 "Chengdu"              timezone=Asia/Chongqing        # China
23.13  113.33 "Guangzhou"            timezone=Asia/Shanghai         # China
45.75  126.68 "Harbin"               timezone=Asia/Harbin           # China
10.75  106.67 "HoChiMinhCity"     timezone=Asia/Saigon           # Vietnam
40.42   -3.72 "Madrid"               timezone=Europe/Madrid         # Spain
-37.75  144.97 "Melbourne"            timezone=Australia/Melbourne   # Australia
35.13  136.88 "Nagoya"               timezone=Asia/Tokyo            # Japan
35.08  129.03 "Pusan"                timezone=Asia/Seoul            # SouthKorea
39.00  125.78 "Pyongyang"            timezone=Asia/Pyongyang        # NorthKorea
41.83  123.43 "Shenyang"             timezone=Asia/Shanghai         # China
1.28  103.85 "Singapore"            timezone=Asia/Singapore        # Singapore
-33.92  151.17 "Sydney"               timezone=Australia/Sydney      # Australia
30.58  114.32 "Wuhan"                timezone=Asia/Shanghai         # China
34.27  108.90 "Xian"                 timezone=Asia/Shanghai         # China
35.47  139.63 "Yokohama"             timezone=Asia/Tokyo            # Japan
23.08 -82.22  "Havana"
9.2 -79.55 "Panama"
-.13 -78.3 "Quito"
-16.3 -68.09 "LaPaz"
-34.53 -56.11 "Montevideo"
-8.03 -34.54 "Recife"
-1.27 -48.28 "Belem"
41.54 12.29 "Rome"
48.13 16.2 "Vienna"
59.55 10.45 "Oslo"
59.2 18.03 "Stockholm"
21.27 39.49 "Mecca"
-31.56 115.5 "Perth"
16.47 96.1 "Rangoon"
21.02 105.51 "Hanoi"
-9.3 147.1 "PortMoresby"
21.18 -157.5 "Honolulu"
61.13 -149.54 "Anchorage"
49.16 -123.07 "Vancouver"
9.02 38.42 "AddisAbaba"
34.3 69.12 "Kabul"
14.1 -17.26 "Dakar"
26.50 128.00 "Okinawa"
ENDOFEARTHCITY;
  return
$earthcity;
}

?>