X-Git-Url: https://git.rapsys.eu/cdn/blobdiff_plain/fc2332aef9324e7766bc70c97b3905d1f396060b..f003b55a5344490d1dadd881c4b68cbd4aee79f4:/public/osm.php diff --git a/public/osm.php b/public/osm.php new file mode 100644 index 0000000..351010e --- /dev/null +++ b/public/osm.php @@ -0,0 +1,268 @@ +osm|osmar|cycle|mapnik)/(?-?[0-9\.]+),(?-?[0-9\.]+),(?[0-9]+)/(?[0-9]+)x(?[0-9]+)\.(?gif|jpe?g|png)$!', $_SERVER['REQUEST_URI'], $_GET)) { + throw new Exception('No request match'); + } + //Cleanup match array + unset($_GET[0], $_GET[1], $_GET[2], $_GET[3], $_GET[4], $_GET[5], $_GET[6], $_GET[7]); +} + +//Check latitude value +if (abs($lt = floatval($_GET['lt'])) > 90) { + throw new Exception('Invalid latitude'); +} + +//Check longitude value +if (abs($ln = floatval($_GET['ln'])) > 180) { + throw new Exception('Invalid longitude'); +} + +//Check zoom value +if (($z = abs(intval($_GET['z']))) > 20) { + throw new Exception('Invalid zoom'); +} + +//Check width value +if (($w = abs(intval($_GET['w']))) > 1024) { + throw new Exception('Invalid width'); +} + +//Check height value +if (($h = abs(intval($_GET['h']))) > 1024) { + throw new Exception('Invalid height'); +} + +//Check type value +if (($t = ($_GET['t']=='mapnik'?'osm':$_GET['t'])) != 'osm' && $t != 'osmar' && $t != 'cycle') { + throw new Exception('Invalid extension'); +} + +//Check extension value +if (($e = ($_GET['e']=='jpeg'?'jpg':$_GET['e'])) != 'gif' && $e != 'jpg' && $e != 'png') { + throw new Exception('Invalid extension'); +} + +//Check imagick presence +if (!class_exists('Imagick')) { + throw new Exception('No imagick class'); +} + +class Osm { + //Set the tile size + const tz = 256; + + //The imagick instance + private $im; + + //Set tile sources + //XXX: see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_servers + protected $uris = [ + 'osm' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png', + 'osmar' => 'http://otile1.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png', + 'cycle' => 'http://a.tile.opencyclemap.org/cycle/{Z}/{X}/{Y}.png', + ]; + + function __construct($t, $lt, $ln, $z, $w, $h, $e) { + //Get tile xy + $tx = floor($cx = $this->lnToTx($ln, $z)); + $ty = floor($cy = $this->ltToTy($lt, $z)); + + //Calculate start xy + $sx = floor(($tx * self::tz - $w) / self::tz); + $sy = floor(($ty * self::tz - $h) / self::tz); + + //Calculate end xy + $ex = floor(($tx * self::tz + $w) / self::tz); + $ey = floor(($ty * self::tz + $h) / self::tz); + + //Create the base image + $this->im = new Imagick(); + $this->im->newImage($w, $h, new ImagickPixel('white'), $e); + + for($x = $sx; $x <= $ex; $x++) { + for($y = $sy; $y <= $ey; $y++) { + //Set file + $file = '../cache/'.$z.'/'.$x.'/'.$y.'.png'; + //Create cache directory + if (!is_dir($dir = dirname($file))) { + mkdir($dir, 0777, true); + } + //Fetch file in cache + if (!file_exists($file)) { + $url = str_replace(['{Z}', '{X}', '{Y}'], [$z, $x, $y], $this->uris[$t]); + file_put_contents($dir.'/'.$y.'.png', file_get_contents($url)); + } + + //Set dest x to + #$dx = ($x - floor($this->centerX - ($this->width / $this->tileSize) / 2)) * $this->tileSize + floor((floor($this->centerX) - $this->centerX) * $this->tileSize); + $dx = ($x - floor($cx - ($w / self::tz) / 2)) * self::tz + floor(($tx - $cx) * self::tz); + #$destY = ($y - $startY) * $this->tileSize + $this->offsetY; + $dy = ($y - floor($cy - ($h / self::tz) / 2)) * self::tz + floor(($ty - $cy) * self::tz); + + //Create tile image + $tm = new Imagick($file); + //Add it at destination + $this->im->compositeImage($tm, imagick::COMPOSITE_COPY, $dx, $dy); + } + } + //Add circle + //XXX: see https://www.php.net/manual/fr/imagick.examples-1.php#example-3916 + $draw = new ImagickDraw(); + $draw->setFillColor('#cff'); + $draw->setStrokeColor('#00c3f9'); + $draw->setStrokeWidth(2); + $draw->circle($w/2 - 5, $h/2 - 5, $w/2 + 5, $h/2 + 5); + $this->im->drawImage($draw); + header('Content-Type: image/'.$e); + echo $this->im; + } + + /** + * Convert longitude to tile x number + * + * @see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_5 + * + * @param $ln The longitude + * @param $z The zoom + * + * @return The tile x + */ + public function lnToTx($ln, $z) { + return (($ln + 180) / 360) * pow(2, $z); + } + + /** + * Convert latitude to tile y number + * + * @see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_5 + * + * @param $lt The latitude + * @param $z The zoom + * + * @return The tile y + */ + public function ltToTy($lt, $z) { + return (1 - log(tan(deg2rad($lt)) + 1 / cos(deg2rad($lt))) / pi()) / 2 * pow(2, $z); + } + + /** + * Convert tile x to longitude + * + * @param $tx The tile x + * @param $z The zoom + * + * @return $ln The longitude + */ + public function txToLn($tx, $z) { + return $tx / pow(2, $z) * 360.0 - 180.0; + } + + /** + * Convert tile y to latitude + * + * @param $ty The tile y + * @param $z The zoom + * + * @return $lt The latitude + */ + public function tyToLt($ty, $z) { + return rad2deg(atan(sinh(pi() * (1 - 2 * $ty / pow(2, $z))))); + } + +} + + +//Match url +header('Content-Type: text/plain'); + +$o = new Osm($t, $lt, $ln, $z, $w, $h, $e); + + /* + //Get center x + $cx = $this->lnToTile($lt, $z); + + //Get center y + $cy = $this->ltToTile($ln, $z); + + //Get offset x + $ox = floor((floor($cx) - $cx) * $tz); + //Get offset y + $oy = floor((floor($cy) - $cy) * $tz); + + //TODO: see this fucking computing + $sx = floor($cx - ($w / $tz) / 2); + $sy = floor($cy - ($h / $tz) / 2); + $ex = ceil($cx + ($w / $tz) / 2); + $ey = ceil($cy + ($h / $tz) / 2); + + $ox = -floor(($cx - floor($cx)) * $tz); + $oy = -floor(($cy - floor($cy)) * $tz); + + $ox += floor($w / 2); + $oy += floor($h / 2); + $ox += floor($sx - floor($cx)) * $tz; + $oy += floor($sy - floor($cy)) * $tz; + */ + + #$ox = floor($tx - floor($tx)) * $tz; + #$oy = floor($ty - floor($ty)) * $tz; + + #var_dump($sx); + #var_dump($cx); + +# var_dump($sx); +# var_dump($tx); +# var_dump($ex); +# var_dump($sy); +# var_dump($ty); +# var_dump($ey); + + #$im->newImage($w, $h, new ImagickPixel('transparent'), $e); + + #for($x = $tx; $x <= $tx; $x++) { + #for($y = $ty; $y <= $ty; $y++) { +# $my = new Imagick($file); + #$my->newImage(5, 5, new ImagickPixel('black'), $e); + +#$this->offsetX = -floor(($this->centerX - floor($this->centerX)) * $this->tileSize); +#$this->offsetY = -floor(($this->centerY - floor($this->centerY)) * $this->tileSize); +#$this->offsetX += floor($this->width / 2); +#$this->offsetY += floor($this->height / 2); +#$this->offsetX += floor($startX - floor($this->centerX)) * $this->tileSize; +#$this->offsetY += floor($startY - floor($this->centerY)) * $this->tileSize; +#$destX = ($x - $startX) * $this->tileSize + $this->offsetX; +#$destY = ($y - $startY) * $this->tileSize + $this->offsetY; +# $this->centerX = $this->lonToTile($this->lon, $this->zoom); +# $this->centerY = $this->latToTile($this->lat, $this->zoom); +# $this->offsetX = floor((floor($this->centerX) - $this->centerX) * $this->tileSize); +# $this->offsetY = floor((floor($this->centerY) - $this->centerY) * $this->tileSize); + +# $im->compositeImage($my, imagick::COMPOSITE_COPY, $dx, $dy); +# #floor($w/2)-floor($tz/2), floor($h/2)-floor($tz/2)); +# header('Content-Type: image/'.$e); +# echo $im; +# exit; +# +# $dx = ($x - $sx) * $tz + floor($w / 2); +# $dy = ($y - $sy) * $tz + floor($h / 2); +# +# var_dump($dx); +# var_dump($dy); +# var_dump(floor($w / 2) - floor(($tx - floor($tx)))); +# exit; +# + #var_dump($url); +# exit; +# $tm = new Imagick($url); +# $im->compositeImage($tm, imagick::COMPOSITE_OVER, $dx, $dy);