Skip to content

Instantly share code, notes, and snippets.

@derickr
Last active May 14, 2024 13:43
Show Gist options
  • Save derickr/0e06c26835ff8ddcf3d62f10403adb8c to your computer and use it in GitHub Desktop.
Save derickr/0e06c26835ff8ddcf3d62f10403adb8c to your computer and use it in GitHub Desktop.
Drawing Image from OpenStreetMap with lines from a GPX file
  1. Run: pecl install geospatial-beta
  2. Create "20-geospatial.ini" in the "Scan for additional .ini files" directory that shows up with "php --ini", with as sole contents: extension=geospatial
  3. Run: composer install
  4. Edit generate-image.php and update to use your name and email — OpenStreetMap servers require this.
  1. Run: generate-image.php <gpxfile>
<?php
require 'vendor/autoload.php';
use DerickR\GPX\Reader;
/* Configuration */
$userAgent = "Your Name/your-email@gmail.com";
$zoomLevel = 12;
$yourLocation = new LatLon( 51.4847, -1.7813 );
$yourLocationSize = 50;
$drawYourLocationBox = true;
$hideFromYourLocationBox = true;
/* Constants, Don't Change */
$tileSize = 256;
$outputFileName = $argv[1] . '.png';
/* Get track data */
$trackData = (new Reader( $argv[1] ))->getTrack()->getTrackData();
/* Finding Boundaries */
$minX = $minY = PHP_INT_MAX;
$maxX = $maxY = PHP_INT_MIN;
foreach ($trackData as $point) {
if ($point[0] < $minX) {
$minX = $point[0];
}
if ($point[0] > $maxX) {
$maxX = $point[0];
}
if ($point[1] < $minY) {
$minY = $point[1];
}
if ($point[1] > $maxY) {
$maxY = $point[1];
}
}
$p1 = new LatLon( $minY, $minX );
$p2 = new LatLon( $maxY, $maxX );
/* Convert Coordinates to Pixels */
$pixels = pow(2, $zoomLevel) * $tileSize;
$x1 = lon2x( $p1->lon, $pixels );
$x2 = lon2x( $p2->lon, $pixels );
$y1 = lat2y( $p2->lat, $pixels );
$y2 = lat2y( $p1->lat, $pixels );
$tx1 = floor( $x1 / $tileSize );
$tx2 = ceil( $x2 / $tileSize );
$ty1 = floor( $y1 / $tileSize );
$ty2 = ceil( $y2 / $tileSize );
$xOrig = $tx1 * $tileSize;
$yOrig = $ty1 * $tileSize;
$yourX = lon2x( $yourLocation->lon, $pixels );
$yourY = lat2y( $yourLocation->lat, $pixels );
$hideX = (floor($yourX / $yourLocationSize) * $yourLocationSize) - $xOrig;
$hideY = (floor($yourY / $yourLocationSize) * $yourLocationSize) - $yOrig;
/* Allocate Image */
$map = imagecreatetruecolor(
( $tx2 - $tx1 ) * $tileSize,
( $ty2 - $ty1 ) * $tileSize
);
imageantialias( $map, true );
/* Define colours */
$red = imagecolorallocate( $map, 200, 0, 0 );
$blue = imagecolorallocate( $map, 0, 0, 200 );
/* Create Image From Tiles */
$ctxt = stream_context_create([ 'http' => [ 'method' => "GET", "header" => "User-Agent: {$userAgent}" ] ]);
for ($i = $tx1; $i < $tx2; $i++) {
for ($j = $ty1; $j < $ty2; $j++) {
echo "https://tile.openstreetmap.org/$zoomLevel/$i/$j.png\n";
$im = imagecreatefromstring( file_get_contents( "https://tile.openstreetmap.org/$zoomLevel/$i/$j.png", false, $ctxt ) );
imagecopy( $map, $im, ($i - $tx1) * $tileSize, ($j - $ty1) * $tileSize, 0, 0, $tileSize, $tileSize );
}
}
/* Draw Your Location Box */
if ( $drawYourLocationBox )
{
imageline( $map, round($hideX), round($hideY), round($hideX + $yourLocationSize), round($hideY), $blue );
imageline( $map, round($hideX + $yourLocationSize), round($hideY), round($hideX + $yourLocationSize), round($hideY + $yourLocationSize), $blue );
imageline( $map, round($hideX + $yourLocationSize), round($hideY + $yourLocationSize), round($hideX), round($hideY + $yourLocationSize), $blue );
imageline( $map, round($hideX), round($hideY + $yourLocationSize), round($hideX), round($hideY), $blue );
}
/* Draw Lines */
for ($i = 0; $i < count($trackData) - 2; $i++) {
$x1 = lon2x( $trackData[$i][0], $pixels ) - $xOrig;
$x2 = lon2x( $trackData[$i+1][0], $pixels ) - $xOrig;
$y1 = lat2y( $trackData[$i][1], $pixels ) - $yOrig;
$y2 = lat2y( $trackData[$i+1][1], $pixels ) - $yOrig;
if ($hideFromYourLocationBox) {
if ($x1 > $hideX && $x1 < ($hideX + $yourLocationSize) && $y1 > $hideY && $y1 < ($hideY + $yourLocationSize)) {
continue;
}
if ($x2 > $hideX && $x2 < ($hideX + $yourLocationSize) && $y2 > $hideY && $y2 < ($hideY + $yourLocationSize)) {
continue;
}
}
imageline( $map, round($x1), round($y1), round($x2), round($y2), $red );
}
/* Add Required Attribution */
imagestring( $map, 5, 10, 10, '(c) OpenStreetMap contributors, CC-BY-SA', imagecolorallocate( $map, 0, 0, 0 ) );
/* Write Image */
imagepng( $map, $outputFileName );
/* Helper Classes and Functions */
class LatLon
{
public $lat;
public $lon;
public $height;
function __construct( $lat, $lon, $height = 0 )
{
$this->lat = $lat;
$this->lon = $lon;
$this->height = $height;
}
}
function lon2x( $lon, $pixels = 32768 )
{
return (($lon + 180) / 360) * $pixels;
}
function lat2y( $lat, $pixels = 32768 )
{
return ((atanh(sin(deg2rad(-$lat))) / M_PI) + 1) * ($pixels / 2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment