Feek
07-04-2010, 16:07
I'd like to be able to generate some maps using openstreetmap and PHP but I know smeg all about PHP to be able to do this.
The map I'd like to start with is this:
http://ocukroguesgallery.com/feek/temp/OpenStreetMap-20100407-155804.jpg
The "Permalink" for it is here:
http://www.openstreetmap.org/?lat=52.34&lon=6.35&zoom=6&layers=B000FTF
I'd like to end up with a map similar to that shown on this (http://wilbert.stoopendaal.com/aprskaart.php) page in that it will have the grid lines and square names overlaid.
I've been in touch with the guy whos site it is and he's provided me with some code.
This first bit is what he uses to overlay stations from his logbook.
define( "HOMELON", 4.4576 ); // longitude home in degrees north
define( "HOMELAT", 51.986 ); // latitude home in degrees east
/*::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::*/
/*:: :*/
/*:: this routine calculates the distance between two points (given the :*/
/*:: latitude/longitude of those points). it is being used to calculate :*/
/*:: the distance between two zip codes or postal codes using our :*/
/*:: zipcodeworld(tm) and postalcodeworld(tm) products. :*/
/*:: :*/
/*:: definitions: :*/
/*:: south latitudes are negative, east longitudes are positive :*/
/*:: :*/
/*:: passed to function: :*/
/*:: lat1, lon1 = latitude and longitude of point 1 (in decimal degrees) :*/
/*:: lat2, lon2 = latitude and longitude of point 2 (in decimal degrees) :*/
/*:: unit = the unit you desire for results :*/
/*:: where: 'm' is statute miles :*/
/*:: 'k' is kilometers (default) :*/
/*:: 'n' is nautical miles :*/
/*:: united states zip code/ canadian postal code databases with latitude & :*/
/*:: longitude are available at http://www.zipcodeworld.com :*/
/*:: :*/
/*:: For enquiries, please contact sales@zipcodeworld.com :*/
/*:: :*/
/*:: official web site: http://www.zipcodeworld.com :*/
/*:: :*/
/*:: hexa software development center © all rights reserved 2004 :*/
/*:: :*/
/*::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::*/
function distance($lat1, $lon1, $lat2 = HOMELAT, $lon2 = HOMELON) {
if (($lat1 == 0) || ($lon1 == 0))
// pech gehad voor iemand precies op de evenaar of 0-mediaan, maar het filtert goed:
{
return -1;
}
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$km = $dist * 60 * 1.852; // 60 minutes in 1 degree, 1852 meters in 1 nautical mile
if ($km > 3000)
return -1; // quick hack voor foute configuraties
return $km;
}
function islocator( $locator )
{
// checkt op een valide locator voor onze berekeningen
$locator = strtoupper( $locator );
return !!preg_match( "/^[A-R][A-R][0-9][0-9][A-X][A-X]$/", $locator );
}
function lon( $locator )
{
// bepaal longitude van een locator
if (!islocator( $locator ))
return FALSE;
$locator = strtoupper( $locator );
$lon = -180 + 20 * (ord( substr( $locator, 0 ) ) - ord( 'A' ));
$lon += 2 * (ord( substr( $locator, 2 ) ) - ord( '0' ));
$lon += 5/60 * (ord( substr( $locator, 4 ) ) - ord( 'A' ));
$lon += 5/60/2; // midden van locatorvak
return $lon;
}
function lat( $locator )
{
// bepaal latitude van een locator
if (!islocator( $locator ))
return FALSE;
$locator = strtoupper( $locator );
$lat = -90 + 10 * (ord( substr( $locator, 1 ) ) - ord( 'A' ));
$lat += 1 * (ord( substr( $locator, 3 ) ) - ord( '0' ));
$lat += 2.5/60 * (ord( substr( $locator, 5 ) ) - ord( 'A' ));
$lat += 2.5/60/2; // midden van locatorvak
return $lat;
}
// http://wiki.openstreetmap.org/wiki/Mercator
function y2lat($a)
{
return 180/M_PI * (2 * atan(exp($a*M_PI/180)) - M_PI/2);
}
function lat2y($a)
{
return 180/M_PI * log(tan(M_PI/4+$a*(M_PI/180)/2));
}
function qthdx( $locator1, $locator2 = 'JO21fx' )
{
// bepaal afstand in kilometers tussen twee Maidenhead locators
if (!islocator( $locator1 ) || !islocator( $locator2 ))
return -1; // foute boel!
if ($locator2 == 'JO21fx')
{
// blijkbaar afstand vanaf huis
return round( distance( lat( $locator1 ), lon( $locator1 ),
HOMELAT, HOMELON ) );
}
else
{
return round( distance( lat( $locator1 ), lon( $locator1 ),
lat( $locator2 ), lon( $locator2 ) ) );
}
}
I asked for the stuff which draws the grid lines and this is what he sent back.
This code should do the job, combined with the earlier supplied code. If you have any questions or need translations, let me know. The function expects a map name and the coordinates of its borders.
It loads the map, draws locatorgrid, put names in locatorsquares and draws concentric circles around the home QTH on the map.
NB The map needs to be in Mercator projection, which is the projection of the maps of Openstreetmap.
function maakaprsplot( $kaart, $lon1, $lat1, $lon2, $lat2 )
{
// laadt kaart
switch (strtolower( substr( $kaart, -3 ) ) )
{
case 'jpg':
$pic = imagecreatefromjpeg( "images/" . $kaart );
break;
case 'png':
$pic = imagecreatefrompng( "images/" . $kaart );
break;
default:
return "Invalid picture: $kaart";
exit( 1 );
}
$breedte = imagesx( $pic );
$lengte = imagesy( $pic );
$kleur = ImageColorAllocate( $pic, 0, 128, 0 );
$aprsrechtstreekskleur = ImageColorAllocate( $pic, 0, 128, 0 );
$aprsnietrechtstreekskleur = ImageColorAllocate( $pic, 128, 0, 0 );
$aprsnietrechtstreekskleur = ImageColorAllocate( $pic, 255, 64, 64 );
$cirkelkleur = ImageColorAllocate( $pic, 128, 128, 128 );
$vakkleur = ImageColorAllocate( $pic, 128, 128, 128 );
$achterkleur = ImageColorAllocate( $pic, 255, 255, 255 );
$lonfactor = $breedte / ($lon2 - $lon1);
$latfactor = $lengte / (lat2y( $lat2 ) - lat2y( $lat1 ));
$lat1m = lat2y( $lat1 ); // corrigeer voor projectie
// teken locatorvakken
for ($lat = 0; $lat < 88; $lat += 1)
{
if ($lat > $lat1 && $lat < $lat2)
{
// valt binnen kaart
$latr = $lengte - ($latfactor * (lat2y( $lat ) - $lat1m));
imageline( $pic, 0, $latr, $breedte - 1, $latr, $vakkleur );
}
}
for ($lon = -90; $lon < 90; $lon += 2)
{
if ($lon > $lon1 && $lon < $lon2)
{
// valt binnen kaart
$lonr = $lonfactor * ($lon - $lon1);
imageline( $pic, $lonr, 0, $lonr, $lengte, $vakkleur );
}
}
// zet namen in locatorvakken
for ($let1 = 'H'; $let1 <= 'L'; $let1++)
for ($let2 = 'M'; $let2 <= 'Q'; $let2++)
for ($cijf = 0; $cijf <= 99; $cijf++)
{
$vak = sprintf( "%s%s%02d", $let1, $let2, $cijf );
$locator = $vak . "ll"; // midden in vak
// echo "|" . $vak . "|";
$lon = round( (lon( $locator ) - $lon1) * $lonfactor );
$lat = $lengte - round( (lat2y( lat( $locator ) ) - $lat1m) * $latfactor );
imagestring( $pic, 3, $lon - 12, $lat - 7, $vak, $vakkleur );
}
// echo "lon1 = " . $lon1 . " lon2 = " . $lon2 . " lat1 = " . $lat1 . " lat2 = " . $lat2 . " lengte = " . $lengte . " latfactor = " . $latfactor . "\n";
// teken cirkels voor afstanden
$homelon = round( (HOMELON - $lon1) * $lonfactor );
$homelat = round( $lengte - ((lat2y( HOMELAT ) - lat2y( $lat1 )) * $latfactor) );
$afstanden = array( 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 );
$afstandfactor = 2 * $lengte / (111.12 * ($lat2 - $lat1)); // 111 km/breedtegraad http://wapedia.mobi/nl/Overleg:Breedtegraad
imagefilledrectangle( $pic, $homelon - 1, $homelat - 1, $homelon + 1, $homelat + 1, $cirkelkleur ); // 0 km ook aangeven!
for ($i = 0; $i < count( $afstanden ); $i++)
{
if (($cirkelgrootte = $afstanden[$i] * $afstandfactor) > 2)
{
imageellipse( $pic, $homelon, $homelat, $afstanden[$i] * $afstandfactor, $afstanden[$i] * $afstandfactor, $cirkelkleur );
if ($cirkelgrootte > 40)
{
imagestring( $pic, 1, $homelon + ($afstanden[$i] * $afstandfactor / 2) + 2, $homelat, ($afstanden[$i]) . " km", $cirkelkleur );
}
}
}
Who fancies having a bash for me? :)
The map I'd like to start with is this:
http://ocukroguesgallery.com/feek/temp/OpenStreetMap-20100407-155804.jpg
The "Permalink" for it is here:
http://www.openstreetmap.org/?lat=52.34&lon=6.35&zoom=6&layers=B000FTF
I'd like to end up with a map similar to that shown on this (http://wilbert.stoopendaal.com/aprskaart.php) page in that it will have the grid lines and square names overlaid.
I've been in touch with the guy whos site it is and he's provided me with some code.
This first bit is what he uses to overlay stations from his logbook.
define( "HOMELON", 4.4576 ); // longitude home in degrees north
define( "HOMELAT", 51.986 ); // latitude home in degrees east
/*::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::*/
/*:: :*/
/*:: this routine calculates the distance between two points (given the :*/
/*:: latitude/longitude of those points). it is being used to calculate :*/
/*:: the distance between two zip codes or postal codes using our :*/
/*:: zipcodeworld(tm) and postalcodeworld(tm) products. :*/
/*:: :*/
/*:: definitions: :*/
/*:: south latitudes are negative, east longitudes are positive :*/
/*:: :*/
/*:: passed to function: :*/
/*:: lat1, lon1 = latitude and longitude of point 1 (in decimal degrees) :*/
/*:: lat2, lon2 = latitude and longitude of point 2 (in decimal degrees) :*/
/*:: unit = the unit you desire for results :*/
/*:: where: 'm' is statute miles :*/
/*:: 'k' is kilometers (default) :*/
/*:: 'n' is nautical miles :*/
/*:: united states zip code/ canadian postal code databases with latitude & :*/
/*:: longitude are available at http://www.zipcodeworld.com :*/
/*:: :*/
/*:: For enquiries, please contact sales@zipcodeworld.com :*/
/*:: :*/
/*:: official web site: http://www.zipcodeworld.com :*/
/*:: :*/
/*:: hexa software development center © all rights reserved 2004 :*/
/*:: :*/
/*::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::*/
function distance($lat1, $lon1, $lat2 = HOMELAT, $lon2 = HOMELON) {
if (($lat1 == 0) || ($lon1 == 0))
// pech gehad voor iemand precies op de evenaar of 0-mediaan, maar het filtert goed:
{
return -1;
}
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$km = $dist * 60 * 1.852; // 60 minutes in 1 degree, 1852 meters in 1 nautical mile
if ($km > 3000)
return -1; // quick hack voor foute configuraties
return $km;
}
function islocator( $locator )
{
// checkt op een valide locator voor onze berekeningen
$locator = strtoupper( $locator );
return !!preg_match( "/^[A-R][A-R][0-9][0-9][A-X][A-X]$/", $locator );
}
function lon( $locator )
{
// bepaal longitude van een locator
if (!islocator( $locator ))
return FALSE;
$locator = strtoupper( $locator );
$lon = -180 + 20 * (ord( substr( $locator, 0 ) ) - ord( 'A' ));
$lon += 2 * (ord( substr( $locator, 2 ) ) - ord( '0' ));
$lon += 5/60 * (ord( substr( $locator, 4 ) ) - ord( 'A' ));
$lon += 5/60/2; // midden van locatorvak
return $lon;
}
function lat( $locator )
{
// bepaal latitude van een locator
if (!islocator( $locator ))
return FALSE;
$locator = strtoupper( $locator );
$lat = -90 + 10 * (ord( substr( $locator, 1 ) ) - ord( 'A' ));
$lat += 1 * (ord( substr( $locator, 3 ) ) - ord( '0' ));
$lat += 2.5/60 * (ord( substr( $locator, 5 ) ) - ord( 'A' ));
$lat += 2.5/60/2; // midden van locatorvak
return $lat;
}
// http://wiki.openstreetmap.org/wiki/Mercator
function y2lat($a)
{
return 180/M_PI * (2 * atan(exp($a*M_PI/180)) - M_PI/2);
}
function lat2y($a)
{
return 180/M_PI * log(tan(M_PI/4+$a*(M_PI/180)/2));
}
function qthdx( $locator1, $locator2 = 'JO21fx' )
{
// bepaal afstand in kilometers tussen twee Maidenhead locators
if (!islocator( $locator1 ) || !islocator( $locator2 ))
return -1; // foute boel!
if ($locator2 == 'JO21fx')
{
// blijkbaar afstand vanaf huis
return round( distance( lat( $locator1 ), lon( $locator1 ),
HOMELAT, HOMELON ) );
}
else
{
return round( distance( lat( $locator1 ), lon( $locator1 ),
lat( $locator2 ), lon( $locator2 ) ) );
}
}
I asked for the stuff which draws the grid lines and this is what he sent back.
This code should do the job, combined with the earlier supplied code. If you have any questions or need translations, let me know. The function expects a map name and the coordinates of its borders.
It loads the map, draws locatorgrid, put names in locatorsquares and draws concentric circles around the home QTH on the map.
NB The map needs to be in Mercator projection, which is the projection of the maps of Openstreetmap.
function maakaprsplot( $kaart, $lon1, $lat1, $lon2, $lat2 )
{
// laadt kaart
switch (strtolower( substr( $kaart, -3 ) ) )
{
case 'jpg':
$pic = imagecreatefromjpeg( "images/" . $kaart );
break;
case 'png':
$pic = imagecreatefrompng( "images/" . $kaart );
break;
default:
return "Invalid picture: $kaart";
exit( 1 );
}
$breedte = imagesx( $pic );
$lengte = imagesy( $pic );
$kleur = ImageColorAllocate( $pic, 0, 128, 0 );
$aprsrechtstreekskleur = ImageColorAllocate( $pic, 0, 128, 0 );
$aprsnietrechtstreekskleur = ImageColorAllocate( $pic, 128, 0, 0 );
$aprsnietrechtstreekskleur = ImageColorAllocate( $pic, 255, 64, 64 );
$cirkelkleur = ImageColorAllocate( $pic, 128, 128, 128 );
$vakkleur = ImageColorAllocate( $pic, 128, 128, 128 );
$achterkleur = ImageColorAllocate( $pic, 255, 255, 255 );
$lonfactor = $breedte / ($lon2 - $lon1);
$latfactor = $lengte / (lat2y( $lat2 ) - lat2y( $lat1 ));
$lat1m = lat2y( $lat1 ); // corrigeer voor projectie
// teken locatorvakken
for ($lat = 0; $lat < 88; $lat += 1)
{
if ($lat > $lat1 && $lat < $lat2)
{
// valt binnen kaart
$latr = $lengte - ($latfactor * (lat2y( $lat ) - $lat1m));
imageline( $pic, 0, $latr, $breedte - 1, $latr, $vakkleur );
}
}
for ($lon = -90; $lon < 90; $lon += 2)
{
if ($lon > $lon1 && $lon < $lon2)
{
// valt binnen kaart
$lonr = $lonfactor * ($lon - $lon1);
imageline( $pic, $lonr, 0, $lonr, $lengte, $vakkleur );
}
}
// zet namen in locatorvakken
for ($let1 = 'H'; $let1 <= 'L'; $let1++)
for ($let2 = 'M'; $let2 <= 'Q'; $let2++)
for ($cijf = 0; $cijf <= 99; $cijf++)
{
$vak = sprintf( "%s%s%02d", $let1, $let2, $cijf );
$locator = $vak . "ll"; // midden in vak
// echo "|" . $vak . "|";
$lon = round( (lon( $locator ) - $lon1) * $lonfactor );
$lat = $lengte - round( (lat2y( lat( $locator ) ) - $lat1m) * $latfactor );
imagestring( $pic, 3, $lon - 12, $lat - 7, $vak, $vakkleur );
}
// echo "lon1 = " . $lon1 . " lon2 = " . $lon2 . " lat1 = " . $lat1 . " lat2 = " . $lat2 . " lengte = " . $lengte . " latfactor = " . $latfactor . "\n";
// teken cirkels voor afstanden
$homelon = round( (HOMELON - $lon1) * $lonfactor );
$homelat = round( $lengte - ((lat2y( HOMELAT ) - lat2y( $lat1 )) * $latfactor) );
$afstanden = array( 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 );
$afstandfactor = 2 * $lengte / (111.12 * ($lat2 - $lat1)); // 111 km/breedtegraad http://wapedia.mobi/nl/Overleg:Breedtegraad
imagefilledrectangle( $pic, $homelon - 1, $homelat - 1, $homelon + 1, $homelat + 1, $cirkelkleur ); // 0 km ook aangeven!
for ($i = 0; $i < count( $afstanden ); $i++)
{
if (($cirkelgrootte = $afstanden[$i] * $afstandfactor) > 2)
{
imageellipse( $pic, $homelon, $homelat, $afstanden[$i] * $afstandfactor, $afstanden[$i] * $afstandfactor, $cirkelkleur );
if ($cirkelgrootte > 40)
{
imagestring( $pic, 1, $homelon + ($afstanden[$i] * $afstandfactor / 2) + 2, $homelat, ($afstanden[$i]) . " km", $cirkelkleur );
}
}
}
Who fancies having a bash for me? :)