Convert Lat Long to php

Hi Guys I was wondering if anyone knows how to convert latitude/longitude coordinates to x and y coordinates to plot on an image. Here is the image. http://www.southernontariochasing.ca/examples/countieswithlogo.png

great job!

Thanks, but I need help on how to convert latitude longitude coordinates from a .txt file to x and y mapping coordinates. Have any ideas on the best way to do this?

Dave,

Do you have the coordinates for the four corners of the image?

Good question. Let me see If I can get them.

Sorry to double post. Give me 10-20 and I will make a placefile and get the image lat and long.

OK pretty sure I have the coords within a few points of a degree… Top Left of image = 45.65030, -84.75925
Bottom Left of Image = 41.49763, -84.35086 Top Right of Image= 45.77540,-76.96502 Bottom Right of Image = 41.61019, -77.07876 , I don’t believe they are 100% exact but close enough for now.

OK,

This code is a mess, but it seems to be working pretty well. I have three test points and I am drawing a 5px red circle on each point. It’s not perfect, but it should illustrate the basic technique you will need to employ. The map is rotated and skewed a little, based on the lat/lon coordinates and I tried to adjust for this as best as possible.

I didn’t comment it (bad habit!), but I will be glad to explain exactly what is going on, once I know it is in line with what you are looking for, or have adjusted it to work accordingly.

jay

[php]<?php

$map = imagecreatefromstring(file_get_contents(‘http://www.southernontariochasing.ca/examples/countieswithlogo.png’));

$test_lat[0] = 41.908665;
$test_lon[0] = -82.509441;
$test_lat[1] = 44.404845;
$test_lon[1] = -79.510918;
$test_lat[2] = 45.021127;
$test_lon[2] = -83.263092;

$pt_lat = $test1_lat;
$pt_lon = $test1_lon;

for($i=0;$i<count($test_lat);$i++)
{
$pt_lat = $test_lat[$i];
$pt_lon = $test_lon[$i];
$map = getx_y($pt_lat,$pt_lon,$map);
}

header(“Content-type: image/png”);
imagepng($map);

function getx_y($pt_lat,$pt_lon,$map)
{
$width = imagesx($map);
$height = imagesy($map);

$mp_lat = 43.69514; // MidPoint
$mp_lon = -80.78972; // MidPoint

$mp_x = round($width/2); //MidPoint x
$mp_y = round($height/2); //MidPOint y

$scale = 1.33; // pixels per kilometer
$rhumb = rhumbDB($mp_lat,$pt_lat,$mp_lon,$pt_lon);

$dist = $rhumb['distance'];
$angle = $rhumb['bearing']+2.2;

$h = $dist * $scale;
$o = sin(deg2rad($angle%90)) * $h;
$a = sqrt(pow($h,2)-pow($o,2));

if($angle > 0 && $angle <= 90)
  {
    $pt_x = $mp_x + $o;
    $pt_y = $mp_y - $a;
  }
elseif($angle > 90 && $angle <= 180)
  {
    $pt_x = $mp_x + $a;
    $pt_y = $mp_y + $o;
  }
elseif($angle > 180 && $angle <= 270)
  {
    $pt_x = $mp_x - $o;
    $pt_y = $mp_y + $a;
  }
elseif($angle > 270 && $angle <= 360)
  {
    $pt_x = $mp_x - $a;
    $pt_y = $mp_y - $o;
  }
  
$dot_color = imagecolorallocate($map, 255, 0, 0);
imagefilledellipse($map, $pt_x, $pt_y, 5, 5, $dot_color);

return $map;

}

function rhumbDB($lat1,$lat2,$lon1,$lon2,$R=6366.71)
{
$lat1 = deg2rad($lat1);
$lat2 = deg2rad($lat2);
$lon1 = deg2rad($lon1);
$lon2 = deg2rad($lon2);
$Δlat = $lat2 - $lat1;
$Δlon = $lon2 - $lon1;

  $ΔPhi = log(tan($lat2/2+M_PI/4)/tan($lat1/2+M_PI/4));
  
  if(is_numeric($Δlat/$ΔPhi)) $q = $Δlat/$ΔPhi;
  else $q = cos($lat1);
  
  if(abs($Δlon) > M_PI)
    {
        if($Δlon > 0) $Δlon = -(2*M_PI-$Δlon);
        else $Δlon = 2*M_PI+$Δlon;
    }
  $d = sqrt($Δlat*$Δlat + $q*$q*$Δlon*$Δlon)*$R;
  $brng = fmod(rad2deg(atan2($Δlon,$ΔPhi))+360,360);
  
  return array('distance'=>$d,'bearing'=>$brng);

}[/php]

Wow thanks so much I will try. If you could explain what it is doing that would be great…im a noob at php as you can tell but im trying to learn as I go. 1 thing…down the road…can I have the script read the lat and long from a .txt file?

I get an error when running the script…probably my mistake…any thoughts? http://www.southernontariochasing.ca/imagewarnings.php

No problem reading from a text file, and I’m happy to explain what is going on. I just want to make sure it is what you are looking for first.

There isn’t much php magic in the code, it is mainly some trig and a lot of tap-dancing. It truly is ugly and probably could be rewritten much better, as it was a lot of stacking code on top of code to get there.

Let me know once you test it…

I’ll look at it and get back to you shortly…

Thanks so much, I really do appreciate the help. I was able to get the warning text side of things done my self with some simple php scripts. This more complex stuff is a little above me right now…but learning as I go

Weird, it works for me…

Lets make sure it isn’t a character encoding issue since I used the delta symbol in my rhumbDB function.

Try this version and see if the problem is still there:[php]<?php

$map = imagecreatefromstring(file_get_contents(‘http://www.southernontariochasing.ca/examples/countieswithlogo.png’));

$test_lat[0] = 41.908665;
$test_lon[0] = -82.509441;
$test_lat[1] = 44.404845;
$test_lon[1] = -79.510918;
$test_lat[2] = 45.021127;
$test_lon[2] = -83.263092;

$pt_lat = $test1_lat;
$pt_lon = $test1_lon;

for($i=0;$i<count($test_lat);$i++)
{
$pt_lat = $test_lat[$i];
$pt_lon = $test_lon[$i];
$map = getx_y($pt_lat,$pt_lon,$map);
}

header(“Content-type: image/png”);
imagepng($map);

function getx_y($pt_lat,$pt_lon,$map)
{
$width = imagesx($map);
$height = imagesy($map);

$mp_lat = 43.69514; // MidPoint
$mp_lon = -80.78972; // MidPoint

$mp_x = round($width/2); //MidPoint x
$mp_y = round($height/2); //MidPOint y

$scale = 1.33; // pixels per kilometer
$rhumb = rhumbDB($mp_lat,$pt_lat,$mp_lon,$pt_lon);

$dist = $rhumb['distance'];
$angle = $rhumb['bearing']+2.2;

$h = $dist * $scale;
$o = sin(deg2rad($angle%90)) * $h;
$a = sqrt(pow($h,2)-pow($o,2));

if($angle > 0 && $angle <= 90)
  {
    $pt_x = $mp_x + $o;
    $pt_y = $mp_y - $a;
  }
elseif($angle > 90 && $angle <= 180)
  {
    $pt_x = $mp_x + $a;
    $pt_y = $mp_y + $o;
  }
elseif($angle > 180 && $angle <= 270)
  {
    $pt_x = $mp_x - $o;
    $pt_y = $mp_y + $a;
  }
elseif($angle > 270 && $angle <= 360)
  {
    $pt_x = $mp_x - $a;
    $pt_y = $mp_y - $o;
  }
  
$dot_color = imagecolorallocate($map, 255, 0, 0);
imagefilledellipse($map, $pt_x, $pt_y, 5, 5, $dot_color);

return $map;

}

function rhumbDB($lat1,$lat2,$lon1,$lon2,$R=6366.71)
{
$lat1 = deg2rad($lat1);
$lat2 = deg2rad($lat2);
$lon1 = deg2rad($lon1);
$lon2 = deg2rad($lon2);
$deltlat = $lat2 - $lat1;
$deltlon = $lon2 - $lon1;

  $deltPhi = log(tan($lat2/2+M_PI/4)/tan($lat1/2+M_PI/4));
  
  if(is_numeric($deltlat/$deltPhi)) $q = $deltlat/$deltPhi;
  else $q = cos($lat1);
  
  if(abs($deltlon) > M_PI)
    {
        if($deltlon > 0) $deltlon = -(2*M_PI-$deltlon);
        else $deltlon = 2*M_PI+$deltlon;
    }
  $d = sqrt($deltlat*$deltlat + $q*$q*$deltlon*$deltlon)*$R;
  $brng = fmod(rad2deg(atan2($deltlon,$deltPhi))+360,360);
  
  return array('distance'=>$d,'bearing'=>$brng);

}[/php]

Works awesome, Image looks awesome. Exactly what I want. Only thing is the .txt files will have polygon coords in them…if the script can make the polygon from the .txt file then i am set.

Good deal!

Can you provide me with an example (maybe cut and paste one polygon array from the text file). I will need to change the dots into a polygon. Once that is working, we will tackle the file reading (should be pretty simple).

Sure thing, Color: 250 1 1
Line: 2, 0, grPoly 1.0
43.61148, -81.30576
43.90381, -80.93029
43.38884, -80.74379
43.21988, -81.31715
43.61148, -81.30576
End:
Breaking that down…the color of the line, then the thickness (disregard the name) and then the lat and long coordinates

OK,

This currently ignores the color and line thickness, but should serve as a test for the polygon generation. See if this looks correct to you:[php]<?php
$map = imagecreatefromstring(file_get_contents(‘http://www.southernontariochasing.ca/examples/countieswithlogo.png’));

$coords = ‘43.61148, -81.30576
43.90381, -80.93029
43.38884, -80.74379
43.21988, -81.31715
43.61148, -81.30576’;

$data = explode(chr(10),$coords);
$oldx = $oldy = NULL;

foreach($data as $coord)
{
list($x,$y) = explode(’,’,$coord);
$result = getx_y($map,$x,$y,$oldx,$oldy);
$map = $result[‘image’];
$oldx = $result[‘oldx’];
$oldy = $result[‘oldy’];
}

header(“Content-type: image/png”); // Send png header to browser
imagepng($map); // Display the image

function getx_y($map,$pt_lat,$pt_lon,$oldx = NULL,$oldy = NULL)
{
$width = imagesx($map);
$height = imagesy($map);

$mp_lat = 43.69514; // MidPoint Latitude
$mp_lon = -80.78972; // MidPoint Longitude

$mp_x = round($width/2); //MidPoint x coordinate
$mp_y = round($height/2); //MidPOint y coordinate

$scale = 1.33; // pixels per kilometer
$rhumb = rhumbDB($mp_lat,$pt_lat,$mp_lon,$pt_lon); // Get rhumb line distance and bearing

$dist = $rhumb['distance']; // Get rhumb line Distance from midpoint
$angle = $rhumb['bearing']+2.2; // Get rhumb line Bearing from midpoint & rotate angle 2.2

$h = $dist * $scale; // Get the scaled distance (in pixels) from midpoint
$o = sin(deg2rad($angle%90)) * $h; // Get the offset in one direction using basic trig
$a = sqrt(pow($h,2)-pow($o,2));  // Get the other offset using pythagorean's theorem

if($angle > 0 && $angle <= 90) // Angle is in the 12:00 to 3:00 quadrant
  {
    $pt_x = $mp_x + $o; //pt_x is to the right of the midpoint
    $pt_y = $mp_y - $a; //pt_y is above the midpoint
  }
elseif($angle > 90 && $angle <= 180) // Angle is in the 3:00 to 6:00 quadrant
  {
    $pt_x = $mp_x + $a; //pt_x is to the right of the midpoint
    $pt_y = $mp_y + $o; //pt_y is below the midpoint
  }
elseif($angle > 180 && $angle <= 270) // Angle is in the 6:00 to 9:00 quadrant
  {
    $pt_x = $mp_x - $o; //pt_x is to the left of the midpoint
    $pt_y = $mp_y + $a; //pt_y is below the midpoint
  }
elseif($angle > 270 && $angle <= 360) // Angle is in the 9:00 to 12:00 quadrant
  {
    $pt_x = $mp_x - $a; //pt_x is to the left of the midpoint
    $pt_y = $mp_y - $o; //pt_y is above the midpoint
  }

$pt_x = round($pt_x); // Make sure pt_x is an integer
$pt_y = round($pt_y); // Make sure pt_y is an integer
  
if(empty($oldx)) $oldx = $pt_x;
if(empty($oldy)) $oldy = $pt_y;
  
$line_color = imagecolorallocate($map, 255, 0, 0);   
imageline($map,$oldx,$oldy,$pt_x,$pt_y,$dot_color);

return array('image'=>$map,'oldx'=>$pt_x,'oldy'=>$pt_y);

}

/*
rhumbDB implements the formula for finding distance and bearing between two points.
The distance and bearing are calculated without regard to great circle routes.
Depending on the map, you may need to use the Haversine formula instead, which accounts
for great circle routes. To return results in miles, use $R=3956.09 instead.*/
function rhumbDB($lat1,$lat2,$lon1,$lon2,$R=6366.71)
{
$lat1 = deg2rad($lat1); // All trig functions need to be in radians
$lat2 = deg2rad($lat2); // All trig functions need to be in radians
$lon1 = deg2rad($lon1); // All trig functions need to be in radians
$lon2 = deg2rad($lon2); // All trig functions need to be in radians
$deltlat = $lat2 - $lat1;
$deltlon = $lon2 - $lon1;

  $deltPhi = log(tan($lat2/2+M_PI/4)/tan($lat1/2+M_PI/4));
  
  if(is_numeric($deltlat/$deltPhi)) $q = $deltlat/$deltPhi;
  else $q = cos($lat1);
  
  if(abs($deltlon) > M_PI)
    {
        if($deltlon > 0) $deltlon = -(2*M_PI-$deltlon);
        else $deltlon = 2*M_PI+$deltlon;
    }
  $d = sqrt($deltlat*$deltlat + $q*$q*$deltlon*$deltlon)*$R;
  $brng = fmod(rad2deg(atan2($deltlon,$deltPhi))+360,360);
  
  return array('distance'=>$d,'bearing'=>$brng);

}[/php]

How important is the line thickness? PHP’s gd library does not support different line weights so we would need to introduce another function to the code in order to accommodate this. It isn’t hard to do, but I wanted to make sure it is necessary before adding it.

Looks fine, looks identical in the program that I created the polygon in. Only thing is color and read all polygons from text file…looks great though. Thanks so much

Here is what it looks like in the program, and then on the map
http://www.southernontariochasing.ca/example.png

Sponsor our Newsletter | Privacy Policy | Terms of Service