]> Raphaƫl G. Git Repositories - cdn/blob - public/osm.php
Add osm map generator
[cdn] / public / osm.php
1 <?php
2
3 //Check for parameter availability
4 if (!isset($_GET['t'])||!isset($_GET['lt'])||!isset($_GET['ln'])||!isset($_GET['z'])||!isset($_GET['w'])||!isset($_GET['h'])||!isset($_GET['e'])) {
5 //Check for uri presence
6 if (empty($_SERVER['REQUEST_URI'])) {
7 throw new Exception('No request uri');
8 }
9 //Check for script name in request uri
10 if (($pos = strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) !== false) {
11 $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 0, $pos).substr($_SERVER['REQUEST_URI'], $pos+strlen($_SERVER['SCRIPT_NAME']));
12 }
13 //Check uri matching
14 if (!preg_match('!^/(?<t>osm|osmar|cycle|mapnik)/(?<lt>-?[0-9\.]+),(?<ln>-?[0-9\.]+),(?<z>[0-9]+)/(?<w>[0-9]+)x(?<h>[0-9]+)\.(?<e>gif|jpe?g|png)$!', $_SERVER['REQUEST_URI'], $_GET)) {
15 throw new Exception('No request match');
16 }
17 //Cleanup match array
18 unset($_GET[0], $_GET[1], $_GET[2], $_GET[3], $_GET[4], $_GET[5], $_GET[6], $_GET[7]);
19 }
20
21 //Check latitude value
22 if (abs($lt = floatval($_GET['lt'])) > 90) {
23 throw new Exception('Invalid latitude');
24 }
25
26 //Check longitude value
27 if (abs($ln = floatval($_GET['ln'])) > 180) {
28 throw new Exception('Invalid longitude');
29 }
30
31 //Check zoom value
32 if (($z = abs(intval($_GET['z']))) > 20) {
33 throw new Exception('Invalid zoom');
34 }
35
36 //Check width value
37 if (($w = abs(intval($_GET['w']))) > 1024) {
38 throw new Exception('Invalid width');
39 }
40
41 //Check height value
42 if (($h = abs(intval($_GET['h']))) > 1024) {
43 throw new Exception('Invalid height');
44 }
45
46 //Check type value
47 if (($t = ($_GET['t']=='mapnik'?'osm':$_GET['t'])) != 'osm' && $t != 'osmar' && $t != 'cycle') {
48 throw new Exception('Invalid extension');
49 }
50
51 //Check extension value
52 if (($e = ($_GET['e']=='jpeg'?'jpg':$_GET['e'])) != 'gif' && $e != 'jpg' && $e != 'png') {
53 throw new Exception('Invalid extension');
54 }
55
56 //Check imagick presence
57 if (!class_exists('Imagick')) {
58 throw new Exception('No imagick class');
59 }
60
61 class Osm {
62 //Set the tile size
63 const tz = 256;
64
65 //The imagick instance
66 private $im;
67
68 //Set tile sources
69 //XXX: see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_servers
70 protected $uris = [
71 'osm' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png',
72 'osmar' => 'http://otile1.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png',
73 'cycle' => 'http://a.tile.opencyclemap.org/cycle/{Z}/{X}/{Y}.png',
74 ];
75
76 function __construct($t, $lt, $ln, $z, $w, $h, $e) {
77 //Get tile xy
78 $tx = floor($cx = $this->lnToTx($ln, $z));
79 $ty = floor($cy = $this->ltToTy($lt, $z));
80
81 //Calculate start xy
82 $sx = floor(($tx * self::tz - $w) / self::tz);
83 $sy = floor(($ty * self::tz - $h) / self::tz);
84
85 //Calculate end xy
86 $ex = floor(($tx * self::tz + $w) / self::tz);
87 $ey = floor(($ty * self::tz + $h) / self::tz);
88
89 //Create the base image
90 $this->im = new Imagick();
91 $this->im->newImage($w, $h, new ImagickPixel('white'), $e);
92
93 for($x = $sx; $x <= $ex; $x++) {
94 for($y = $sy; $y <= $ey; $y++) {
95 //Set file
96 $file = '../cache/'.$z.'/'.$x.'/'.$y.'.png';
97 //Create cache directory
98 if (!is_dir($dir = dirname($file))) {
99 mkdir($dir, 0777, true);
100 }
101 //Fetch file in cache
102 if (!file_exists($file)) {
103 $url = str_replace(['{Z}', '{X}', '{Y}'], [$z, $x, $y], $this->uris[$t]);
104 file_put_contents($dir.'/'.$y.'.png', file_get_contents($url));
105 }
106
107 //Set dest x to
108 #$dx = ($x - floor($this->centerX - ($this->width / $this->tileSize) / 2)) * $this->tileSize + floor((floor($this->centerX) - $this->centerX) * $this->tileSize);
109 $dx = ($x - floor($cx - ($w / self::tz) / 2)) * self::tz + floor(($tx - $cx) * self::tz);
110 #$destY = ($y - $startY) * $this->tileSize + $this->offsetY;
111 $dy = ($y - floor($cy - ($h / self::tz) / 2)) * self::tz + floor(($ty - $cy) * self::tz);
112
113 //Create tile image
114 $tm = new Imagick($file);
115 //Add it at destination
116 $this->im->compositeImage($tm, imagick::COMPOSITE_COPY, $dx, $dy);
117 }
118 }
119 //Add circle
120 //XXX: see https://www.php.net/manual/fr/imagick.examples-1.php#example-3916
121 $draw = new ImagickDraw();
122 $draw->setFillColor('#cff');
123 $draw->setStrokeColor('#00c3f9');
124 $draw->setStrokeWidth(2);
125 $draw->circle($w/2 - 5, $h/2 - 5, $w/2 + 5, $h/2 + 5);
126 $this->im->drawImage($draw);
127 header('Content-Type: image/'.$e);
128 echo $this->im;
129 }
130
131 /**
132 * Convert longitude to tile x number
133 *
134 * @see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_5
135 *
136 * @param $ln The longitude
137 * @param $z The zoom
138 *
139 * @return The tile x
140 */
141 public function lnToTx($ln, $z) {
142 return (($ln + 180) / 360) * pow(2, $z);
143 }
144
145 /**
146 * Convert latitude to tile y number
147 *
148 * @see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_5
149 *
150 * @param $lt The latitude
151 * @param $z The zoom
152 *
153 * @return The tile y
154 */
155 public function ltToTy($lt, $z) {
156 return (1 - log(tan(deg2rad($lt)) + 1 / cos(deg2rad($lt))) / pi()) / 2 * pow(2, $z);
157 }
158
159 /**
160 * Convert tile x to longitude
161 *
162 * @param $tx The tile x
163 * @param $z The zoom
164 *
165 * @return $ln The longitude
166 */
167 public function txToLn($tx, $z) {
168 return $tx / pow(2, $z) * 360.0 - 180.0;
169 }
170
171 /**
172 * Convert tile y to latitude
173 *
174 * @param $ty The tile y
175 * @param $z The zoom
176 *
177 * @return $lt The latitude
178 */
179 public function tyToLt($ty, $z) {
180 return rad2deg(atan(sinh(pi() * (1 - 2 * $ty / pow(2, $z)))));
181 }
182
183 }
184
185
186 //Match url
187 header('Content-Type: text/plain');
188
189 $o = new Osm($t, $lt, $ln, $z, $w, $h, $e);
190
191 /*
192 //Get center x
193 $cx = $this->lnToTile($lt, $z);
194
195 //Get center y
196 $cy = $this->ltToTile($ln, $z);
197
198 //Get offset x
199 $ox = floor((floor($cx) - $cx) * $tz);
200 //Get offset y
201 $oy = floor((floor($cy) - $cy) * $tz);
202
203 //TODO: see this fucking computing
204 $sx = floor($cx - ($w / $tz) / 2);
205 $sy = floor($cy - ($h / $tz) / 2);
206 $ex = ceil($cx + ($w / $tz) / 2);
207 $ey = ceil($cy + ($h / $tz) / 2);
208
209 $ox = -floor(($cx - floor($cx)) * $tz);
210 $oy = -floor(($cy - floor($cy)) * $tz);
211
212 $ox += floor($w / 2);
213 $oy += floor($h / 2);
214 $ox += floor($sx - floor($cx)) * $tz;
215 $oy += floor($sy - floor($cy)) * $tz;
216 */
217
218 #$ox = floor($tx - floor($tx)) * $tz;
219 #$oy = floor($ty - floor($ty)) * $tz;
220
221 #var_dump($sx);
222 #var_dump($cx);
223
224 # var_dump($sx);
225 # var_dump($tx);
226 # var_dump($ex);
227 # var_dump($sy);
228 # var_dump($ty);
229 # var_dump($ey);
230
231 #$im->newImage($w, $h, new ImagickPixel('transparent'), $e);
232
233 #for($x = $tx; $x <= $tx; $x++) {
234 #for($y = $ty; $y <= $ty; $y++) {
235 # $my = new Imagick($file);
236 #$my->newImage(5, 5, new ImagickPixel('black'), $e);
237
238 #$this->offsetX = -floor(($this->centerX - floor($this->centerX)) * $this->tileSize);
239 #$this->offsetY = -floor(($this->centerY - floor($this->centerY)) * $this->tileSize);
240 #$this->offsetX += floor($this->width / 2);
241 #$this->offsetY += floor($this->height / 2);
242 #$this->offsetX += floor($startX - floor($this->centerX)) * $this->tileSize;
243 #$this->offsetY += floor($startY - floor($this->centerY)) * $this->tileSize;
244 #$destX = ($x - $startX) * $this->tileSize + $this->offsetX;
245 #$destY = ($y - $startY) * $this->tileSize + $this->offsetY;
246 # $this->centerX = $this->lonToTile($this->lon, $this->zoom);
247 # $this->centerY = $this->latToTile($this->lat, $this->zoom);
248 # $this->offsetX = floor((floor($this->centerX) - $this->centerX) * $this->tileSize);
249 # $this->offsetY = floor((floor($this->centerY) - $this->centerY) * $this->tileSize);
250
251 # $im->compositeImage($my, imagick::COMPOSITE_COPY, $dx, $dy);
252 # #floor($w/2)-floor($tz/2), floor($h/2)-floor($tz/2));
253 # header('Content-Type: image/'.$e);
254 # echo $im;
255 # exit;
256 #
257 # $dx = ($x - $sx) * $tz + floor($w / 2);
258 # $dy = ($y - $sy) * $tz + floor($h / 2);
259 #
260 # var_dump($dx);
261 # var_dump($dy);
262 # var_dump(floor($w / 2) - floor(($tx - floor($tx))));
263 # exit;
264 #
265 #var_dump($url);
266 # exit;
267 # $tm = new Imagick($url);
268 # $im->compositeImage($tm, imagick::COMPOSITE_OVER, $dx, $dy);