This commit is contained in:
Malte Hübner 2018-02-19 07:32:28 +00:00 committed by GitHub
commit 426480a342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 2768 additions and 411 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
.idea/
vendor

26
composer.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "calderacc/staticmaplite",
"type": "library",
"license": "Apache",
"authors": [
{
"name": "Gerhard Koch",
"email": "gerhard.koch@ymail.com"
},
{
"name": "Malte Hübner",
"email": "maltehuebner@gmx.org"
}
],
"autoload": {
"psr-4": {
"StaticMapLite\\": "src"
}
},
"minimum-stability": "stable",
"require": {
"emcconville/google-map-polyline-encoding-tool": "^1.3",
"curl/curl": "^1.6",
"imagine/imagine": "^0.7.1"
}
}

176
composer.lock generated Normal file
View File

@ -0,0 +1,176 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "11486d8639a42e3b06c8b99e7ff5061a",
"packages": [
{
"name": "curl/curl",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/php-mod/curl.git",
"reference": "96f5bd47bab8d76f1883c257c6659091987ef662"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mod/curl/zipball/96f5bd47bab8d76f1883c257c6659091987ef662",
"reference": "96f5bd47bab8d76f1883c257c6659091987ef662",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"squizlabs/php_codesniffer": "~2.1"
},
"type": "library",
"autoload": {
"psr-0": {
"Curl": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Hassan Amouhzi",
"email": "hassan@anezi.net",
"homepage": "http://hassan.amouhzi.com"
},
{
"name": "php-curl-class",
"homepage": "https://github.com/php-curl-class"
},
{
"name": "user52",
"homepage": "https://github.com/user52"
}
],
"description": "cURL class for PHP",
"homepage": "https://github.com/php-mod/curl",
"keywords": [
"curl",
"dot"
],
"time": "2017-04-03T15:04:35+00:00"
},
{
"name": "emcconville/google-map-polyline-encoding-tool",
"version": "v1.3",
"source": {
"type": "git",
"url": "https://github.com/emcconville/google-map-polyline-encoding-tool.git",
"reference": "dbf3816936620b88f0fc4000fddd94b5ce13eadb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/emcconville/google-map-polyline-encoding-tool/zipball/dbf3816936620b88f0fc4000fddd94b5ce13eadb",
"reference": "dbf3816936620b88f0fc4000fddd94b5ce13eadb",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "4.1.*",
"satooshi/php-coveralls": "dev-master",
"squizlabs/php_codesniffer": "2.0.0a2"
},
"type": "library",
"autoload": {
"files": [
"src/Polyline.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GNU"
],
"authors": [
{
"name": "Eric McConville",
"email": "emcconville@emcconville.com"
}
],
"description": "A simple class to handle polyline-encoding for Google Maps",
"keywords": [
"google",
"maps"
],
"time": "2016-04-05T01:18:39+00:00"
},
{
"name": "imagine/imagine",
"version": "v0.7.1",
"source": {
"type": "git",
"url": "https://github.com/avalanche123/Imagine.git",
"reference": "a9a702a946073cbca166718f1b02a1e72d742daa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/avalanche123/Imagine/zipball/a9a702a946073cbca166718f1b02a1e72d742daa",
"reference": "a9a702a946073cbca166718f1b02a1e72d742daa",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"sami/sami": "^3.3",
"symfony/phpunit-bridge": "^3.2"
},
"suggest": {
"ext-gd": "to use the GD implementation",
"ext-gmagick": "to use the Gmagick implementation",
"ext-imagick": "to use the Imagick implementation"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "0.7-dev"
}
},
"autoload": {
"psr-0": {
"Imagine": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bulat Shakirzyanov",
"email": "mallluhuct@gmail.com",
"homepage": "http://avalanche123.com"
}
],
"description": "Image processing for PHP 5.3",
"homepage": "http://imagine.readthedocs.org/",
"keywords": [
"drawing",
"graphics",
"image manipulation",
"image processing"
],
"time": "2017-05-16T10:31:22+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

Binary file not shown.

BIN
images/extramarkers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

79
src/Canvas/Canvas.php Normal file
View File

@ -0,0 +1,79 @@
<?php
namespace StaticMapLite\Canvas;
use Imagine\Image\ImageInterface;
class Canvas implements CanvasInterface
{
/** @var ImageInterface $image */
protected $image = null;
/** @var int $tileSize */
protected $tileSize = 256;
/** @var int $width */
protected $width = 0;
/** @var int $height */
protected $height = 0;
/** @var float $centerX */
protected $centerX = 0;
/** @var float $centerY */
protected $centerY = 0;
/** @var int $zoom */
protected $zoom = 0;
public function __construct(int $width, int $height, int $zoom, float $centerX, float $centerY)
{
$this->width = $width;
$this->height = $height;
$this->zoom = $zoom;
$this->centerX = $centerX;
$this->centerY = $centerY;
$imagine = new \Imagine\Gd\Imagine();
$size = new \Imagine\Image\Box($this->width, $this->height);
$this->image = $imagine->create($size);
}
public function getImage(): ImageInterface
{
return $this->image;
}
public function getWidth(): int
{
return $this->width;
}
public function getHeight(): int
{
return $this->height;
}
public function getCenterX(): float
{
return $this->centerX;
}
public function getCenterY(): float
{
return $this->centerY;
}
public function getZoom(): int
{
return $this->zoom;
}
public function getTileSize(): int
{
return $this->tileSize;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace StaticMapLite\Canvas;
use Imagine\Image\ImageInterface;
interface CanvasInterface
{
public function getImage(): ImageInterface;
public function getWidth(): int;
public function getHeight(): int;
public function getCenterX(): float;
public function getCenterY(): float;
public function getZoom(): int;
public function getTileSize(): int;
}

View File

@ -0,0 +1,102 @@
<?php
namespace StaticMapLite\CanvasTilePainter;
use Imagine\Gd\Imagine;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;
use Imagine\Image\Point;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\TileResolver\TileResolverInterface;
class CanvasTilePainter
{
/** @var Canvas $canvas */
protected $canvas;
/** @var TileResolverInterface $tileResolver */
protected $tileResolver;
/** @var ImageInterface $tmpCanvasImage */
protected $tmpCanvasImage;
public function __construct()
{
}
public function setCanvas(Canvas $canvas): CanvasTilePainter
{
$this->canvas = $canvas;
return $this;
}
public function setTileResolver(TileResolverInterface $tileResolver): CanvasTilePainter
{
$this->tileResolver = $tileResolver;
return $this;
}
protected function createTmpCanvasImage(): CanvasTilePainter
{
$tileSize = $this->canvas->getTileSize();
$size = new Box($this->canvas->getWidth() + 2 * $tileSize, $this->canvas->getHeight() + 2 * $tileSize);
$imagine = new Imagine();
$this->tmpCanvasImage = $imagine->create($size);
return $this;
}
protected function cropToCanvas(): CanvasTilePainter
{
$tmpTopLeftPoint = new Point(256, 256);
$this->tmpCanvasImage->crop($tmpTopLeftPoint, $this->canvas->getImage()->getSize());
$topLeftPoint = new Point(0, 0);
$this->canvas->getImage()->paste($this->tmpCanvasImage, $topLeftPoint);
return $this;
}
public function paint(): CanvasTilePainter
{
$this->createTmpCanvasImage();
$startX = floor($this->canvas->getCenterX() - ($this->canvas->getWidth() / $this->canvas->getTileSize()) / 2);
$startY = floor($this->canvas->getCenterY() - ($this->canvas->getHeight() / $this->canvas->getTileSize()) / 2);
$endX = ceil($this->canvas->getCenterX() + ($this->canvas->getWidth() / $this->canvas->getTileSize()) / 2);
$endY = ceil($this->canvas->getCenterY() + ($this->canvas->getHeight() / $this->canvas->getTileSize()) / 2);
$offsetX = -floor(($this->canvas->getCenterX() - floor($this->canvas->getCenterX())) * $this->canvas->getTileSize());
$offsetY = -floor(($this->canvas->getCenterY() - floor($this->canvas->getCenterY())) * $this->canvas->getTileSize());
$offsetX += floor($this->canvas->getWidth() / 2);
$offsetY += floor($this->canvas->getHeight() / 2);
$offsetX += floor($startX - floor($this->canvas->getCenterX())) * $this->canvas->getTileSize();
$offsetY += floor($startY - floor($this->canvas->getCenterY())) * $this->canvas->getTileSize();
$box = new Box(256, 256);
for ($x = $startX; $x <= $endX; $x++) {
for ($y = $startY; $y <= $endY; $y++) {
$tileImage = $this->tileResolver->fetch($this->canvas->getZoom(), $x, $y);
$destX = ($x - $startX) * $this->canvas->getTileSize() + $offsetX;
$destY = ($y - $startY) * $this->canvas->getTileSize() + $offsetY;
$point = new Point($destX + 256, $destY + 256);
if ($this->tmpCanvasImage->getSize()->contains($box, $point)) {
$this->tmpCanvasImage->paste($tileImage, $point);
}
}
}
$this->cropToCanvas();
return $this;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace StaticMapLite\CanvasTilePainter;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\TileResolver\TileResolver;
interface CanvasTilePainterInterface
{
public function setCanvas(Canvas $canvas): CanvasTilePainterInterface;
public function setTileResolver(TileResolver $tileResolver): CanvasTilePainterInterface;
public function paint(): CanvasTilePainterInterface;
}

View File

@ -0,0 +1,41 @@
<?php
namespace StaticMapLite\CopyrightPrinter;
use Imagine\Gd\Imagine;
use Imagine\Image\Point;
use StaticMapLite\Canvas\CanvasInterface;
class CopyrightPrinter implements CopyrightPrinterInterface
{
/** @var string $copyrightPath */
protected $copyrightPath = '../images/osm_logo.png';
/** @var CanvasInterface $canvas */
protected $canvas;
/** @var int $offset */
protected $offset = 10;
public function setCanvas(CanvasInterface $canvas): CopyrightPrinterInterface
{
$this->canvas = $canvas;
return $this;
}
public function printCopyright(): CopyrightPrinterInterface
{
$imagine = new Imagine();
$copyrightImage = $imagine->open($this->copyrightPath);
$canvasSize = $this->canvas->getImage()->getSize();
$copyrightSize = $copyrightImage->getSize();
$point = new Point($canvasSize->getWidth() - $copyrightSize->getWidth() - $this->offset,$canvasSize->getHeight() - $copyrightSize->getHeight() - $this->offset);
$this->canvas->getImage()->paste($copyrightImage, $point);
return $this;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace StaticMapLite\CopyrightPrinter;
interface CopyrightPrinterInterface
{
}

View File

@ -0,0 +1,688 @@
<?php
namespace StaticMapLite\Element\Factory\Marker;
use StaticMapLite\Element\Marker\ExtraMarker;
use StaticMapLite\Exception\ExtraMarker\InvalidColorException;
use StaticMapLite\Exception\ExtraMarker\InvalidIconException;
use StaticMapLite\Exception\ExtraMarker\InvalidShapeException;
class ExtraMarkerFactory
{
public function create(float $latitude, float $longitude, string $shape, string $color, string $icon): ExtraMarker
{
return new ExtraMarker($this->getShape($shape), $this->getColor($color), $this->getAwesome($icon), $latitude, $longitude);
}
protected function getAwesome(string $icon): string
{
$icons = [
'glass' => 'f000',
'music' => 'f001',
'search' => 'f002',
'envelope-o' => 'f003',
'heart' => 'f004',
'star' => 'f005',
'star-o' => 'f006',
'user' => 'f007',
'film' => 'f008',
'th-large' => 'f009',
'th' => 'f00a',
'th-list' => 'f00b',
'check' => 'f00c',
'times' => 'f00d',
'search-plus' => 'f00e',
'search-minus' => 'f010',
'power-off' => 'f011',
'signal' => 'f012',
'cog' => 'f013',
'trash-o' => 'f014',
'home' => 'f015',
'file-o' => 'f016',
'clock-o' => 'f017',
'road' => 'f018',
'download' => 'f019',
'arrow-circle-o-down' => 'f01a',
'arrow-circle-o-up' => 'f01b',
'inbox' => 'f01c',
'play-circle-o' => 'f01d',
'repeat' => 'f01e',
'refresh' => 'f021',
'list-alt' => 'f022',
'lock' => 'f023',
'flag' => 'f024',
'headphones' => 'f025',
'volume-off' => 'f026',
'volume-down' => 'f027',
'volume-up' => 'f028',
'qrcode' => 'f029',
'barcode' => 'f02a',
'tag' => 'f02b',
'tags' => 'f02c',
'book' => 'f02d',
'bookmark' => 'f02e',
'print' => 'f02f',
'camera' => 'f030',
'font' => 'f031',
'bold' => 'f032',
'italic' => 'f033',
'text-height' => 'f034',
'text-width' => 'f035',
'align-left' => 'f036',
'align-center' => 'f037',
'align-right' => 'f038',
'align-justify' => 'f039',
'list' => 'f03a',
'outdent' => 'f03b',
'indent' => 'f03c',
'video-camera' => 'f03d',
'picture-o' => 'f03e',
'pencil' => 'f040',
'map-marker' => 'f041',
'adjust' => 'f042',
'tint' => 'f043',
'pencil-square-o' => 'f044',
'share-square-o' => 'f045',
'check-square-o' => 'f046',
'arrows' => 'f047',
'step-backward' => 'f048',
'fast-backward' => 'f049',
'backward' => 'f04a',
'play' => 'f04b',
'pause' => 'f04c',
'stop' => 'f04d',
'forward' => 'f04e',
'fast-forward' => 'f050',
'step-forward' => 'f051',
'eject' => 'f052',
'chevron-left' => 'f053',
'chevron-right' => 'f054',
'plus-circle' => 'f055',
'minus-circle' => 'f056',
'times-circle' => 'f057',
'check-circle' => 'f058',
'question-circle' => 'f059',
'info-circle' => 'f05a',
'crosshairs' => 'f05b',
'times-circle-o' => 'f05c',
'check-circle-o' => 'f05d',
'ban' => 'f05e',
'arrow-left' => 'f060',
'arrow-right' => 'f061',
'arrow-up' => 'f062',
'arrow-down' => 'f063',
'share' => 'f064',
'expand' => 'f065',
'compress' => 'f066',
'plus' => 'f067',
'minus' => 'f068',
'asterisk' => 'f069',
'exclamation-circle' => 'f06a',
'gift' => 'f06b',
'leaf' => 'f06c',
'fire' => 'f06d',
'eye' => 'f06e',
'eye-slash' => 'f070',
'exclamation-triangle' => 'f071',
'plane' => 'f072',
'calendar' => 'f073',
'random' => 'f074',
'comment' => 'f075',
'magnet' => 'f076',
'chevron-up' => 'f077',
'chevron-down' => 'f078',
'retweet' => 'f079',
'shopping-cart' => 'f07a',
'folder' => 'f07b',
'folder-open' => 'f07c',
'arrows-v' => 'f07d',
'arrows-h' => 'f07e',
'bar-chart' => 'f080',
'twitter-square' => 'f081',
'facebook-square' => 'f082',
'camera-retro' => 'f083',
'key' => 'f084',
'cogs' => 'f085',
'comments' => 'f086',
'thumbs-o-up' => 'f087',
'thumbs-o-down' => 'f088',
'star-half' => 'f089',
'heart-o' => 'f08a',
'sign-out' => 'f08b',
'linkedin-square' => 'f08c',
'thumb-tack' => 'f08d',
'external-link' => 'f08e',
'sign-in' => 'f090',
'trophy' => 'f091',
'github-square' => 'f092',
'upload' => 'f093',
'lemon-o' => 'f094',
'phone' => 'f095',
'square-o' => 'f096',
'bookmark-o' => 'f097',
'phone-square' => 'f098',
'twitter' => 'f099',
'facebook' => 'f09a',
'github' => 'f09b',
'unlock' => 'f09c',
'credit-card' => 'f09d',
'rss' => 'f09e',
'hdd-o' => 'f0a0',
'bullhorn' => 'f0a1',
'bell' => 'f0f3',
'certificate' => 'f0a3',
'hand-o-right' => 'f0a4',
'hand-o-left' => 'f0a5',
'hand-o-up' => 'f0a6',
'hand-o-down' => 'f0a7',
'arrow-circle-left' => 'f0a8',
'arrow-circle-right' => 'f0a9',
'arrow-circle-up' => 'f0aa',
'arrow-circle-down' => 'f0ab',
'globe' => 'f0ac',
'wrench' => 'f0ad',
'tasks' => 'f0ae',
'filter' => 'f0b0',
'briefcase' => 'f0b1',
'arrows-alt' => 'f0b2',
'users' => 'f0c0',
'link' => 'f0c1',
'cloud' => 'f0c2',
'flask' => 'f0c3',
'scissors' => 'f0c4',
'files-o' => 'f0c5',
'paperclip' => 'f0c6',
'floppy-o' => 'f0c7',
'square' => 'f0c8',
'bars' => 'f0c9',
'list-ul' => 'f0ca',
'list-ol' => 'f0cb',
'strikethrough' => 'f0cc',
'underline' => 'f0cd',
'table' => 'f0ce',
'magic' => 'f0d0',
'truck' => 'f0d1',
'pinterest' => 'f0d2',
'pinterest-square' => 'f0d3',
'google-plus-square' => 'f0d4',
'google-plus' => 'f0d5',
'money' => 'f0d6',
'caret-down' => 'f0d7',
'caret-up' => 'f0d8',
'caret-left' => 'f0d9',
'caret-right' => 'f0da',
'columns' => 'f0db',
'sort' => 'f0dc',
'sort-desc' => 'f0dd',
'sort-asc' => 'f0de',
'envelope' => 'f0e0',
'linkedin' => 'f0e1',
'undo' => 'f0e2',
'gavel' => 'f0e3',
'tachometer' => 'f0e4',
'comment-o' => 'f0e5',
'comments-o' => 'f0e6',
'bolt' => 'f0e7',
'sitemap' => 'f0e8',
'umbrella' => 'f0e9',
'clipboard' => 'f0ea',
'lightbulb-o' => 'f0eb',
'exchange' => 'f0ec',
'cloud-download' => 'f0ed',
'cloud-upload' => 'f0ee',
'user-md' => 'f0f0',
'stethoscope' => 'f0f1',
'suitcase' => 'f0f2',
'bell-o' => 'f0a2',
'coffee' => 'f0f4',
'cutlery' => 'f0f5',
'file-text-o' => 'f0f6',
'building-o' => 'f0f7',
'hospital-o' => 'f0f8',
'ambulance' => 'f0f9',
'medkit' => 'f0fa',
'fighter-jet' => 'f0fb',
'beer' => 'f0fc',
'h-square' => 'f0fd',
'plus-square' => 'f0fe',
'angle-double-left' => 'f100',
'angle-double-right' => 'f101',
'angle-double-up' => 'f102',
'angle-double-down' => 'f103',
'angle-left' => 'f104',
'angle-right' => 'f105',
'angle-up' => 'f106',
'angle-down' => 'f107',
'desktop' => 'f108',
'laptop' => 'f109',
'tablet' => 'f10a',
'mobile' => 'f10b',
'circle-o' => 'f10c',
'quote-left' => 'f10d',
'quote-right' => 'f10e',
'spinner' => 'f110',
'circle' => 'f111',
'reply' => 'f112',
'github-alt' => 'f113',
'folder-o' => 'f114',
'folder-open-o' => 'f115',
'smile-o' => 'f118',
'frown-o' => 'f119',
'meh-o' => 'f11a',
'gamepad' => 'f11b',
'keyboard-o' => 'f11c',
'flag-o' => 'f11d',
'flag-checkered' => 'f11e',
'terminal' => 'f120',
'code' => 'f121',
'reply-all' => 'f122',
'star-half-o' => 'f123',
'location-arrow' => 'f124',
'crop' => 'f125',
'code-fork' => 'f126',
'chain-broken' => 'f127',
'question' => 'f128',
'info' => 'f129',
'exclamation' => 'f12a',
'superscript' => 'f12b',
'subscript' => 'f12c',
'eraser' => 'f12d',
'puzzle-piece' => 'f12e',
'microphone' => 'f130',
'microphone-slash' => 'f131',
'shield' => 'f132',
'calendar-o' => 'f133',
'fire-extinguisher' => 'f134',
'rocket' => 'f135',
'maxcdn' => 'f136',
'chevron-circle-left' => 'f137',
'chevron-circle-right' => 'f138',
'chevron-circle-up' => 'f139',
'chevron-circle-down' => 'f13a',
'html5' => 'f13b',
'css3' => 'f13c',
'anchor' => 'f13d',
'unlock-alt' => 'f13e',
'bullseye' => 'f140',
'ellipsis-h' => 'f141',
'ellipsis-v' => 'f142',
'rss-square' => 'f143',
'play-circle' => 'f144',
'ticket' => 'f145',
'minus-square' => 'f146',
'minus-square-o' => 'f147',
'level-up' => 'f148',
'level-down' => 'f149',
'check-square' => 'f14a',
'pencil-square' => 'f14b',
'external-link-square' => 'f14c',
'share-square' => 'f14d',
'compass' => 'f14e',
'caret-square-o-down' => 'f150',
'caret-square-o-up' => 'f151',
'caret-square-o-right' => 'f152',
'eur' => 'f153',
'gbp' => 'f154',
'usd' => 'f155',
'inr' => 'f156',
'jpy' => 'f157',
'rub' => 'f158',
'krw' => 'f159',
'btc' => 'f15a',
'file' => 'f15b',
'file-text' => 'f15c',
'sort-alpha-asc' => 'f15d',
'sort-alpha-desc' => 'f15e',
'sort-amount-asc' => 'f160',
'sort-amount-desc' => 'f161',
'sort-numeric-asc' => 'f162',
'sort-numeric-desc' => 'f163',
'thumbs-up' => 'f164',
'thumbs-down' => 'f165',
'youtube-square' => 'f166',
'youtube' => 'f167',
'xing' => 'f168',
'xing-square' => 'f169',
'youtube-play' => 'f16a',
'dropbox' => 'f16b',
'stack-overflow' => 'f16c',
'instagram' => 'f16d',
'flickr' => 'f16e',
'adn' => 'f170',
'bitbucket' => 'f171',
'bitbucket-square' => 'f172',
'tumblr' => 'f173',
'tumblr-square' => 'f174',
'long-arrow-down' => 'f175',
'long-arrow-up' => 'f176',
'long-arrow-left' => 'f177',
'long-arrow-right' => 'f178',
'apple' => 'f179',
'windows' => 'f17a',
'android' => 'f17b',
'linux' => 'f17c',
'dribbble' => 'f17d',
'skype' => 'f17e',
'foursquare' => 'f180',
'trello' => 'f181',
'female' => 'f182',
'male' => 'f183',
'gratipay' => 'f184',
'sun-o' => 'f185',
'moon-o' => 'f186',
'archive' => 'f187',
'bug' => 'f188',
'vk' => 'f189',
'weibo' => 'f18a',
'renren' => 'f18b',
'pagelines' => 'f18c',
'stack-exchange' => 'f18d',
'arrow-circle-o-right' => 'f18e',
'arrow-circle-o-left' => 'f190',
'caret-square-o-left' => 'f191',
'dot-circle-o' => 'f192',
'wheelchair' => 'f193',
'vimeo-square' => 'f194',
'try' => 'f195',
'plus-square-o' => 'f196',
'space-shuttle' => 'f197',
'slack' => 'f198',
'envelope-square' => 'f199',
'wordpress' => 'f19a',
'openid' => 'f19b',
'university' => 'f19c',
'graduation-cap' => 'f19d',
'yahoo' => 'f19e',
'google' => 'f1a0',
'reddit' => 'f1a1',
'reddit-square' => 'f1a2',
'stumbleupon-circle' => 'f1a3',
'stumbleupon' => 'f1a4',
'delicious' => 'f1a5',
'digg' => 'f1a6',
'pied-piper-pp' => 'f1a7',
'pied-piper-alt' => 'f1a8',
'drupal' => 'f1a9',
'joomla' => 'f1aa',
'language' => 'f1ab',
'fax' => 'f1ac',
'building' => 'f1ad',
'child' => 'f1ae',
'paw' => 'f1b0',
'spoon' => 'f1b1',
'cube' => 'f1b2',
'cubes' => 'f1b3',
'behance' => 'f1b4',
'behance-square' => 'f1b5',
'steam' => 'f1b6',
'steam-square' => 'f1b7',
'recycle' => 'f1b8',
'car' => 'f1b9',
'taxi' => 'f1ba',
'tree' => 'f1bb',
'spotify' => 'f1bc',
'deviantart' => 'f1bd',
'soundcloud' => 'f1be',
'database' => 'f1c0',
'file-pdf-o' => 'f1c1',
'file-word-o' => 'f1c2',
'file-excel-o' => 'f1c3',
'file-powerpoint-o' => 'f1c4',
'file-image-o' => 'f1c5',
'file-archive-o' => 'f1c6',
'file-audio-o' => 'f1c7',
'file-video-o' => 'f1c8',
'file-code-o' => 'f1c9',
'vine' => 'f1ca',
'codepen' => 'f1cb',
'jsfiddle' => 'f1cc',
'life-ring' => 'f1cd',
'circle-o-notch' => 'f1ce',
'rebel' => 'f1d0',
'empire' => 'f1d1',
'git-square' => 'f1d2',
'git' => 'f1d3',
'hacker-news' => 'f1d4',
'tencent-weibo' => 'f1d5',
'qq' => 'f1d6',
'weixin' => 'f1d7',
'paper-plane' => 'f1d8',
'paper-plane-o' => 'f1d9',
'history' => 'f1da',
'circle-thin' => 'f1db',
'header' => 'f1dc',
'paragraph' => 'f1dd',
'sliders' => 'f1de',
'share-alt' => 'f1e0',
'share-alt-square' => 'f1e1',
'bomb' => 'f1e2',
'futbol-o' => 'f1e3',
'tty' => 'f1e4',
'binoculars' => 'f1e5',
'plug' => 'f1e6',
'slideshare' => 'f1e7',
'twitch' => 'f1e8',
'yelp' => 'f1e9',
'newspaper-o' => 'f1ea',
'wifi' => 'f1eb',
'calculator' => 'f1ec',
'paypal' => 'f1ed',
'google-wallet' => 'f1ee',
'cc-visa' => 'f1f0',
'cc-mastercard' => 'f1f1',
'cc-discover' => 'f1f2',
'cc-amex' => 'f1f3',
'cc-paypal' => 'f1f4',
'cc-stripe' => 'f1f5',
'bell-slash' => 'f1f6',
'bell-slash-o' => 'f1f7',
'trash' => 'f1f8',
'copyright' => 'f1f9',
'at' => 'f1fa',
'eyedropper' => 'f1fb',
'paint-brush' => 'f1fc',
'birthday-cake' => 'f1fd',
'area-chart' => 'f1fe',
'pie-chart' => 'f200',
'line-chart' => 'f201',
'lastfm' => 'f202',
'lastfm-square' => 'f203',
'toggle-off' => 'f204',
'toggle-on' => 'f205',
'bicycle' => 'f206',
'bus' => 'f207',
'ioxhost' => 'f208',
'angellist' => 'f209',
'cc' => 'f20a',
'ils' => 'f20b',
'meanpath' => 'f20c',
'buysellads' => 'f20d',
'connectdevelop' => 'f20e',
'dashcube' => 'f210',
'forumbee' => 'f211',
'leanpub' => 'f212',
'sellsy' => 'f213',
'shirtsinbulk' => 'f214',
'simplybuilt' => 'f215',
'skyatlas' => 'f216',
'cart-plus' => 'f217',
'cart-arrow-down' => 'f218',
'diamond' => 'f219',
'ship' => 'f21a',
'user-secret' => 'f21b',
'motorcycle' => 'f21c',
'street-view' => 'f21d',
'heartbeat' => 'f21e',
'venus' => 'f221',
'mars' => 'f222',
'mercury' => 'f223',
'transgender' => 'f224',
'transgender-alt' => 'f225',
'venus-double' => 'f226',
'mars-double' => 'f227',
'venus-mars' => 'f228',
'mars-stroke' => 'f229',
'mars-stroke-v' => 'f22a',
'mars-stroke-h' => 'f22b',
'neuter' => 'f22c',
'genderless' => 'f22d',
'facebook-official' => 'f230',
'pinterest-p' => 'f231',
'whatsapp' => 'f232',
'server' => 'f233',
'user-plus' => 'f234',
'user-times' => 'f235',
'bed' => 'f236',
'viacoin' => 'f237',
'train' => 'f238',
'subway' => 'f239',
'medium' => 'f23a',
'y-combinator' => 'f23b',
'optin-monster' => 'f23c',
'opencart' => 'f23d',
'expeditedssl' => 'f23e',
'battery-full' => 'f240',
'battery-three-quarters' => 'f241',
'battery-half' => 'f242',
'battery-quarter' => 'f243',
'battery-empty' => 'f244',
'mouse-pointer' => 'f245',
'i-cursor' => 'f246',
'object-group' => 'f247',
'object-ungroup' => 'f248',
'sticky-note' => 'f249',
'sticky-note-o' => 'f24a',
'cc-jcb' => 'f24b',
'cc-diners-club' => 'f24c',
'clone' => 'f24d',
'balance-scale' => 'f24e',
'hourglass-o' => 'f250',
'hourglass-start' => 'f251',
'hourglass-half' => 'f252',
'hourglass-end' => 'f253',
'hourglass' => 'f254',
'hand-rock-o' => 'f255',
'hand-paper-o' => 'f256',
'hand-scissors-o' => 'f257',
'hand-lizard-o' => 'f258',
'hand-spock-o' => 'f259',
'hand-pointer-o' => 'f25a',
'hand-peace-o' => 'f25b',
'trademark' => 'f25c',
'registered' => 'f25d',
'creative-commons' => 'f25e',
'gg' => 'f260',
'gg-circle' => 'f261',
'tripadvisor' => 'f262',
'odnoklassniki' => 'f263',
'odnoklassniki-square' => 'f264',
'get-pocket' => 'f265',
'wikipedia-w' => 'f266',
'safari' => 'f267',
'chrome' => 'f268',
'firefox' => 'f269',
'opera' => 'f26a',
'internet-explorer' => 'f26b',
'television' => 'f26c',
'contao' => 'f26d',
'500px' => 'f26e',
'amazon' => 'f270',
'calendar-plus-o' => 'f271',
'calendar-minus-o' => 'f272',
'calendar-times-o' => 'f273',
'calendar-check-o' => 'f274',
'industry' => 'f275',
'map-pin' => 'f276',
'map-signs' => 'f277',
'map-o' => 'f278',
'map' => 'f279',
'commenting' => 'f27a',
'commenting-o' => 'f27b',
'houzz' => 'f27c',
'vimeo' => 'f27d',
'black-tie' => 'f27e',
'fonticons' => 'f280',
'reddit-alien' => 'f281',
'edge' => 'f282',
'credit-card-alt' => 'f283',
'codiepie' => 'f284',
'modx' => 'f285',
'fort-awesome' => 'f286',
'usb' => 'f287',
'product-hunt' => 'f288',
'mixcloud' => 'f289',
'scribd' => 'f28a',
'pause-circle' => 'f28b',
'pause-circle-o' => 'f28c',
'stop-circle' => 'f28d',
'stop-circle-o' => 'f28e',
'shopping-bag' => 'f290',
'shopping-basket' => 'f291',
'hashtag' => 'f292',
'bluetooth' => 'f293',
'bluetooth-b' => 'f294',
'percent' => 'f295',
'gitlab' => 'f296',
'wpbeginner' => 'f297',
'wpforms' => 'f298',
'envira' => 'f299',
'universal-access' => 'f29a',
'wheelchair-alt' => 'f29b',
'question-circle-o' => 'f29c',
'blind' => 'f29d',
'audio-description' => 'f29e',
'volume-control-phone' => 'f2a0',
'braille' => 'f2a1',
'assistive-listening-systems' => 'f2a2',
'american-sign-language-interpreting' => 'f2a3',
'deaf' => 'f2a4',
'glide' => 'f2a5',
'glide-g' => 'f2a6',
'sign-language' => 'f2a7',
'low-vision' => 'f2a8',
'viadeo' => 'f2a9',
'viadeo-square' => 'f2aa',
'snapchat' => 'f2ab',
'snapchat-ghost' => 'f2ac',
'snapchat-square' => 'f2ad',
'pied-piper' => 'f2ae',
'first-order' => 'f2b0',
'yoast' => 'f2b1',
'themeisle' => 'f2b2',
'google-plus-official' => 'f2b3',
'font-awesome' => 'f2b4'
];
if (!array_key_exists($icon, $icons)) {
throw new InvalidIconException(sprintf('The icon "%s" is not available', $icon));
}
return $icons[$icon];
}
protected function getShape(string $shape): int
{
$shapes = ['circle', 'square', 'star', 'penta'];
$key = array_search($shape, $shapes);
if (false === $key) {
throw new InvalidShapeException(sprintf('The shape "%s" is not available', $shape));
}
return $key;
}
protected function getColor(string $color): int
{
$colors = ['red', 'orangedark', 'orange', 'yellow', 'bluedark', 'blue', 'cyan', 'purple', 'violet', 'pink', 'greendark', 'green', 'greenlight', 'black', 'white'];
$key = array_search($color, $colors);
if (false === $key) {
new InvalidColorException(sprintf('The color "%s" is not available', $color));
}
return $key;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Created by PhpStorm.
* User: maltehuebner
* Date: 29.09.17
* Time: 15:46
*/
namespace StaticMapLite\Element\Marker;
class AbstractMarker
{
protected $latitude;
protected $longitude;
public function getLatitude(): float
{
return $this->latitude;
}
public function getLongitude(): float
{
return $this->longitude;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace StaticMapLite\Element\Marker;
class ExtraMarker extends AbstractMarker
{
const SHAPE_CIRCLE = 0;
const SHAPE_SQUARE = 1;
const SHAPE_STAR = 2;
const SHAPE_PENTA = 3;
const COLOR_RED = 0;
const COLOR_ORANGEDARK = 1;
const COLOR_ORANGE = 2;
const COLOR_YELLOW = 3;
const COLOR_BLUEDARK = 4;
const COLOR_BLUE = 5;
const COLOR_CYAN = 6;
const COLOR_PURPLE = 7;
const COLOR_VIOLET = 8;
const COLOR_PINK = 9;
const COLOR_GREENDARK = 10;
const COLOR_GREEN = 11;
const COLOR_GREENLIGHT = 12;
const COLOR_BLACK = 13;
const COLOR_WHITE = 14;
protected $shape;
protected $color;
protected $awesome;
public function __construct(int $shape, int $color, string $awesome, float $latitude, float $longitude)
{
$this->shape = $shape;
$this->color = $color;
$this->awesome = $awesome;
$this->latitude = $latitude;
$this->longitude = $longitude;
}
public function getShape(): int
{
return $this->shape;
}
public function getColor(): int
{
return $this->color;
}
public function getAwesome(): string
{
return $this->awesome;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace StaticMapLite\Element\Marker;
/** @deprecated */
class Marker extends AbstractMarker
{
protected $markerType;
public function __construct(string $markerType, float $latitude, float $longitude)
{
$this->markerType = $markerType;
$this->latitude = $latitude;
$this->longitude = $longitude;
}
public function getMarkerType(): string
{
return $this->markerType;
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace StaticMapLite\Element\Polyline;
class Polyline
{
/** @var string $polyline */
protected $polyline = null;
/** @var int $colorRed */
protected $colorRed = 0;
/** @var int $colorGreen */
protected $colorGreen = 0;
/** @var int $colorBlue */
protected $colorBlue = 0;
public function __construct(string $polyline, int $colorRed = 0, int $colorGreen = 0, int $colorBlue = 0)
{
$this->polyline = $polyline;
$this->colorRed = $colorRed;
$this->colorGreen = $colorGreen;
$this->colorBlue = $colorBlue;
}
public function getPolyline(): string
{
return $this->polyline;
}
public function getColorRed(): int
{
return $this->colorRed;
}
public function getColorGreen(): int
{
return $this->colorGreen;
}
public function getColorBlue(): int
{
return $this->colorBlue;
}
}

View File

@ -0,0 +1,173 @@
<?php
namespace StaticMapLite\ElementPrinter\Marker;
use Imagine\Gd\Font;
use Imagine\Image\AbstractFont;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;
use Imagine\Image\ImagineInterface;
use Imagine\Image\Point;
use Imagine\Image\Point\Center;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\Element\Marker\AbstractMarker;
use StaticMapLite\Element\Marker\ExtraMarker;
use StaticMapLite\Util;
class ExtraMarkerPrinter
{
/** @var int $iconOffsetX */
protected $iconOffsetX = 0;
/** @var int $iconOffsetY */
protected $iconOffsetY = -12;
/** @var int $shadowOffsetX */
protected $shadowOffsetX = 24;
/** @var int $shadowOffsetY */
protected $shadowOffsetY = 18;
/** @var ImagineInterface $imagine */
protected $imagine;
/** @var ExtraMarker $marker */
protected $marker = null;
/** @var int $baseMarkerWidth */
protected $baseMarkerWidth = 72;
/** @var int $baseMarkerHeight */
protected $baseMarkerHeight = 92;
/** @var int $baseShadowWidth */
protected $baseShadowWidth = 21;
/** @var int $baseShadowHeight */
protected $baseShadowHeight = 14;
/** @var float $markerSize */
protected $markerSize = 0.75;
public function __construct()
{
$this->imagine = new \Imagine\Gd\Imagine();
}
public function setMarkerSize(float $markerSize): ExtraMarkerPrinter
{
$this->markerSize = $markerSize;
return $this;
}
public function setMarker(AbstractMarker $marker): ExtraMarkerPrinter
{
$this->marker = $marker;
return $this;
}
public function paint(Canvas $canvas): ExtraMarkerPrinter
{
$this->paintShadow($canvas);
$this->paintMarker($canvas);
return $this;
}
protected function paintMarker(Canvas $canvas): ExtraMarkerPrinter
{
$markerImage = $this->createMarker();
$destX = floor(($canvas->getWidth() / 2) - $canvas->getTileSize() * ($canvas->getCenterX() - Util::lonToTile($this->marker->getLongitude(), $canvas->getZoom())));
$destY = floor(($canvas->getHeight() / 2) - $canvas->getTileSize() * ($canvas->getCenterY() - Util::latToTile($this->marker->getLatitude(), $canvas->getZoom())));
$destX -= $markerImage->getSize()->getWidth() * $this->markerSize / 2;
$destY -= $markerImage->getSize()->getHeight() * $this->markerSize;
$point = new Point($destX, $destY);
if ($canvas->getImage()->getSize()->contains($markerImage->getSize(), $point)) {
$canvas->getImage()->paste($markerImage, $point);
}
return $this;
}
protected function createMarker(): ImageInterface
{
$extramarkers = $this
->imagine
->open(__DIR__.'/../../../images/extramarkers.png')
;
$sourceX = $this->baseMarkerWidth * $this->marker->getColor();
$sourceY = $this->baseMarkerHeight * $this->marker->getShape();
$point = new Point($sourceX, $sourceY);
$box = new Box($this->baseMarkerWidth, $this->baseMarkerHeight);
$markerImage = $extramarkers->crop($point, $box);
$this->writeMarker($markerImage);
return $markerImage;
}
protected function writeMarker(ImageInterface $markerImage): ExtraMarkerPrinter
{
$text = json_decode(sprintf('"&#x%s;"', $this->marker->getAwesome()));
$font = $this->getFont($markerImage);
$textBox = $font->box($text);
$textCenterPosition = new Center($textBox);
$imageCenterPosition = new Center($markerImage->getSize());
$centeredTextPosition = new Point(
$imageCenterPosition->getX() - $textCenterPosition->getX() + $this->iconOffsetX,
$imageCenterPosition->getY() - $textCenterPosition->getY() + $this->iconOffsetY
);
$markerImage->draw()->text($text, $font, $centeredTextPosition);
return $this;
}
protected function getFont(ImageInterface $markerImage): AbstractFont
{
$fontColor = $markerImage->palette()->color('fff');
$fontSize = 20;
$fontFilename = __DIR__.'/../../../fonts/fontawesome-webfont.ttf';
$font = new Font($fontFilename, $fontSize, $fontColor);
return $font;
}
protected function paintShadow(Canvas $canvas): ExtraMarkerPrinter
{
$shadowImage = $this->createShadow();
$destX = floor(($canvas->getWidth() / 2) - $canvas->getTileSize() * ($canvas->getCenterX() - Util::lonToTile($this->marker->getLongitude(), $canvas->getZoom())));
$destY = floor(($canvas->getHeight() / 2) - $canvas->getTileSize() * ($canvas->getCenterY() - Util::latToTile($this->marker->getLatitude(), $canvas->getZoom())));
$destX -= $this->baseShadowWidth * $this->markerSize;
$destY -= $this->baseShadowHeight;
$point = new Point($destX + $this->shadowOffsetX, $destY + $this->shadowOffsetY);
$canvas->getImage()->paste($shadowImage, $point);
return $this;
}
protected function createShadow(): ImageInterface
{
$shadowImage = $this
->imagine
->open(__DIR__.'/../../../images/marker_shadow.png')
;
return $shadowImage;
}
}

View File

@ -0,0 +1,123 @@
<?php
namespace StaticMapLite\ElementPrinter\Marker;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\Element\Marker\AbstractMarker;
use StaticMapLite\Element\Marker\Marker;
use StaticMapLite\Util;
/** @deprecated */
class MarkerPrinter
{
/** @var Marker $marker */
protected $marker = null;
protected $markerBaseDir = '../images/markers';
protected $markerPrototypes = array(
// found at http://www.mapito.net/map-marker-icons.html
'lighblue' => array('regex' => '/^lightblue([0-9]+)$/',
'extension' => '.png',
'shadow' => false,
'offsetImage' => '0,-19',
'offsetShadow' => false,
),
// openlayers std markers
'ol-marker' => array('regex' => '/^ol-marker(|-blue|-gold|-green)+$/',
'extension' => '.png',
'shadow' => '../marker_shadow.png',
'offsetImage' => '-10,-25',
'offsetShadow' => '-1,-13',
),
// taken from http://www.visual-case.it/cgi-bin/vc/GMapsIcons.pl
'ylw' => array('regex' => '/^(pink|purple|red|ltblu|ylw)-pushpin$/',
'extension' => '.png',
'shadow' => '../marker_shadow.png',
'offsetImage' => '-10,-32',
'offsetShadow' => '-1,-13',
),
// http://svn.openstreetmap.org/sites/other/StaticMap/symbols/0.png
'ojw' => array('regex' => '/^bullseye$/',
'extension' => '.png',
'shadow' => false,
'offsetImage' => '-20,-20',
'offsetShadow' => false,
),
);
public function __construct()
{
}
public function setMarker(AbstractMarker $marker): MarkerPrinter
{
$this->marker = $marker;
return $this;
}
public function paint(Canvas $canvas): MarkerPrinter
{
$markerFilename = '';
$markerShadow = '';
$matches = false;
$markerIndex = 0;
// check for marker type, get settings from markerPrototypes
if ($this->marker->getMarkerType()) {
foreach ($this->markerPrototypes as $markerPrototype) {
if (preg_match($markerPrototype['regex'], $this->marker->getMarkerType(), $matches)) {
$markerFilename = $matches[0] . $markerPrototype['extension'];
if ($markerPrototype['offsetImage']) {
list($markerImageOffsetX, $markerImageOffsetY) = explode(",", $markerPrototype['offsetImage']);
}
$markerShadow = $markerPrototype['shadow'];
if ($markerShadow) {
list($markerShadowOffsetX, $markerShadowOffsetY) = explode(",", $markerPrototype['offsetShadow']);
}
}
}
}
// check required files or set default
if ($markerFilename == '' || !file_exists($this->markerBaseDir . '/' . $markerFilename)) {
$markerIndex++;
$markerFilename = 'lightblue' . $markerIndex . '.png';
$markerImageOffsetX = 0;
$markerImageOffsetY = -19;
}
// create img resource
if (file_exists($this->markerBaseDir . '/' . $markerFilename)) {
$markerImg = imagecreatefrompng($this->markerBaseDir . '/' . $markerFilename);
} else {
$markerImg = imagecreatefrompng($this->markerBaseDir . '/lightblue1.png');
}
// check for shadow + create shadow recource
if ($markerShadow && file_exists($this->markerBaseDir . '/' . $markerShadow)) {
$markerShadowImg = imagecreatefrompng($this->markerBaseDir . '/' . $markerShadow);
}
// calc position
$destX = floor(($canvas->getWidth() / 2) - $canvas->getTileSize() * ($canvas->getCenterX() - Util::lonToTile($this->marker->getLongitude(), $canvas->getZoom())));
$destY = floor(($canvas->getHeight() / 2) - $canvas->getTileSize() * ($canvas->getCenterY() - Util::latToTile($this->marker->getLatitude(), $canvas->getZoom())));
// copy shadow on basemap
if ($markerShadow && $markerShadowImg) {
imagecopy($canvas->getImage(), $markerShadowImg, $destX + intval($markerShadowOffsetX), $destY + intval($markerShadowOffsetY),
0, 0, imagesx($markerShadowImg), imagesy($markerShadowImg));
}
// copy marker on basemap above shadow
imagecopy($canvas->getImage(), $markerImg, $destX + intval($markerImageOffsetX), $destY + intval($markerImageOffsetY),
0, 0, imagesx($markerImg), imagesy($markerImg));
return $this;
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace StaticMapLite\ElementPrinter\Polyline;
use Imagine\Image\Palette\Color\ColorInterface;
use Imagine\Image\Point;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\Element\Polyline\Polyline;
use StaticMapLite\Util;
class PolylinePrinter
{
/** @var int $thickness */
protected $thickness = 3;
/** @var Polyline $polyline */
protected $polyline = null;
public function __construct()
{
}
public function setPolyline(Polyline $polyline): PolylinePrinter
{
$this->polyline = $polyline;
return $this;
}
public function paint(Canvas $canvas): PolylinePrinter
{
$pointList = $this->convertPolylineToPointList($canvas);
$color = $this->getPolylineColor($canvas);
$startPoint = null;
$endPoint = null;
while (!empty($pointList)) {
if (!$startPoint) {
$startPoint = array_pop($pointList);
}
$endPoint = array_pop($pointList);
$canvas->getImage()->draw()->line($startPoint, $endPoint, $color, $this->thickness);
$startPoint = $endPoint;
}
return $this;
}
protected function getPolylineColor(Canvas $canvas): ColorInterface
{
return $canvas->getImage()->palette()->color([
$this->polyline->getColorRed(),
$this->polyline->getColorGreen(),
$this->polyline->getColorBlue(),
]);
}
protected function convertPolylineToPointList(Canvas $canvas): array
{
$polylineList = \Polyline::decode($this->polyline->getPolyline());
$pointList = [];
while (!empty($polylineList)) {
$latitude = array_shift($polylineList);
$longitude = array_shift($polylineList);
$sourceX = floor(($canvas->getWidth() / 2) - $canvas->getTileSize() * ($canvas->getCenterX() - Util::lonToTile($longitude, $canvas->getZoom())));
$sourceY = floor(($canvas->getHeight() / 2) - $canvas->getTileSize() * ($canvas->getCenterY() - Util::latToTile($latitude, $canvas->getZoom())));
$point = new Point($sourceX, $sourceY);
$pointList[] = $point;
}
return $pointList;
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace StaticMapLite\Exception\ExtraMarker;
use StaticMapLite\Exception\MapException;
class InvalidColorException extends MapException
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace StaticMapLite\Exception\ExtraMarker;
use StaticMapLite\Exception\MapException;
class InvalidIconException extends MapException
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace StaticMapLite\Exception\ExtraMarker;
use StaticMapLite\Exception\MapException;
class InvalidShapeException extends MapException
{
}

View File

@ -0,0 +1,8 @@
<?php
namespace StaticMapLite\Exception;
class MapException extends \Exception
{
}

102
src/MapCache/MapCache.php Normal file
View File

@ -0,0 +1,102 @@
<?php
namespace StaticMapLite\MapCache;
use StaticMapLite\Canvas\CanvasInterface;
use StaticMapLite\Output\CacheOutput;
use StaticMapLite\Output\OutputInterface;
use StaticMapLite\Printer\PrinterInterface;
class MapCache
{
/** @var PrinterInterface $printer */
protected $printer;
/** @var bool $useMapCache */
protected $useMapCache = false;
/** @var string $mapCacheBaseDir */
protected $mapCacheBaseDir = '../cache/maps';
/** @var string $mapCacheID */
protected $mapCacheID = '';
/** @var string $mapCacheFile */
protected $mapCacheFile = '';
/** @var string $mapCacheExtension */
protected $mapCacheExtension = 'png';
public function __construct(PrinterInterface $printer)
{
$this->printer = $printer;
}
public function checkMapCache(): bool
{
return false;
$this->mapCacheID = md5($this->serializeParams());
$filename = $this->getFilename();
return file_exists($filename);
}
public function serializeParams(): string
{
return join('&', [
$this->printer->getZoom(),
$this->printer->getLatitude(),
$this->printer->getLongitude(),
$this->printer->getWidth(),
$this->printer->getHeight(),
serialize($this->printer->getMarkers()),
serialize($this->printer->getPolylines()),
$this->printer->getMapType()
]);
}
public function mapCacheIDToFilename()
{
if (!$this->mapCacheFile) {
$this->mapCacheFile = sprintf(
'%s/%s/%s/cache_%/%s/%s',
$this->mapCacheBaseDir,
$this->printer->getMaptype(),
$this->printer->getZoom(),
substr($this->mapCacheID, 0, 2),
substr($this->mapCacheID, 2, 2),
substr($this->mapCacheID, 4)
);
}
$filename = sprintf('%s.%s', $this->mapCacheFile, $this->mapCacheExtension);
return $filename;
}
public function cache(CanvasInterface $canvas): void
{
$this->mkdir_recursive(dirname($this->mapCacheIDToFilename()), 0777);
$canvas->getImage()->save($this->mapCacheIDToFilename());
$output = new CacheOutput();
$output->setFilename($this->mapCacheIDToFilename())
->sendHeader()
->sendImage()
;
}
public function mkdir_recursive($pathname, $mode): bool
{
is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode);
return is_dir($pathname) || @mkdir($pathname, $mode);
}
public function getFilename(): string
{
return $this->mapCacheIDToFilename();
}
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: maltehuebner
* Date: 14.02.18
* Time: 09:31
*/
namespace StaticMapLite\MapCache;
interface MapCacheInterface
{
}

View File

@ -0,0 +1,17 @@
<?php
namespace StaticMapLite\Output;
abstract class AbstractOutput implements OutputInterface
{
public function sendHeader(): OutputInterface
{
header('Content-Type: image/png');
$expires = 60 * 60 * 24 * 14;
header('Pragma: public');
header('Cache-Control: maxage=' . $expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
return $this;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace StaticMapLite\Output;
class CacheOutput extends AbstractOutput
{
protected $filename;
public function setFilename($filename): OutputInterface
{
$this->filename = $filename;
return $this;
}
public function sendImage(): void
{
echo file_get_contents($this->filename);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace StaticMapLite\Output;
class ImageOutput extends AbstractOutput
{
protected $image;
public function setImage($image): OutputInterface
{
$this->image = $image;
return $this;
}
public function sendImage(): bool
{
return imagepng($this->image);
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace StaticMapLite\Output;
interface OutputInterface
{
public function sendHeader();
public function sendImage();
}

View File

@ -0,0 +1,340 @@
<?php
namespace StaticMapLite\Printer;
use StaticMapLite\Canvas\CanvasInterface;
use StaticMapLite\MapCache\MapCache;
use StaticMapLite\MapCache\MapCacheInterface;
use StaticMapLite\TileResolver\TileResolverInterface;
abstract class AbstractPrinter implements PrinterInterface
{
/** @var MapCacheInterface $mapCache */
protected $mapCache;
/** @var int $maxWidth */
protected $maxWidth = 1024;
/** @var int $maxHeight */
protected $maxHeight = 1024;
/** @var TileResolverInterface */
protected $tileResolver;
/** @var CanvasInterface $canvas */
protected $canvas;
/** @var int $tileSize */
protected $tileSize = 256;
/** @var array $tileSrcUrl */
protected $tileSrcUrl = [
'mapnik' => 'http://tile.openstreetmap.org/{z}/{x}/{y}.png',
'osmarenderer' => 'http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png',
'cycle' => 'http://a.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png',
'wikimedia-intl' => 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png',
];
/** @var string $tileDefaultSrc */
protected $tileDefaultSrc = 'mapnik';
/** @var bool $useTileCache */
protected $useTileCache = true;
/** @var int $zoom */
protected $zoom;
/** @var float $latitude */
protected $latitude;
/** @var float $longitude */
protected $longitude;
/** @var int $width */
protected $width;
/** @var int $height */
protected $height;
protected $image;
protected $maptype;
protected $centerX;
protected $centerY;
protected $offsetX;
protected $offsetY;
/** @var array $markers */
protected $markers = [];
/** @var array $polylines */
protected $polylines = [];
public function getMaxWidth(): int
{
return $this->maxWidth;
}
public function setMaxWidth(int $maxWidth): PrinterInterface
{
$this->maxWidth = $maxWidth;
return $this;
}
public function getMaxHeight(): int
{
return $this->maxHeight;
}
public function setMaxHeight(int $maxHeight): PrinterInterface
{
$this->maxHeight = $maxHeight;
return $this;
}
public function getTileResolver(): TileResolverInterface
{
return $this->tileResolver;
}
public function setTileResolver(TileResolverInterface $tileResolver): PrinterInterface
{
$this->tileResolver = $tileResolver;
return $this;
}
public function getCanvas(): CanvasInterface
{
return $this->canvas;
}
public function setCanvas(CanvasInterface $canvas): PrinterInterface
{
$this->canvas = $canvas;
return $this;
}
public function getTileSize(): int
{
return $this->tileSize;
}
public function setTileSize(int $tileSize): PrinterInterface
{
$this->tileSize = $tileSize;
return $this;
}
public function getTileSrcUrl(): array
{
return $this->tileSrcUrl;
}
public function setTileSrcUrl(array $tileSrcUrl): PrinterInterface
{
$this->tileSrcUrl = $tileSrcUrl;
return $this;
}
public function getTileDefaultSrc(): string
{
return $this->tileDefaultSrc;
}
public function setTileDefaultSrc(string $tileDefaultSrc): PrinterInterface
{
$this->tileDefaultSrc = $tileDefaultSrc;
return $this;
}
public function getOsmLogo(): string
{
return $this->osmLogo;
}
public function setOsmLogo(string $osmLogo): PrinterInterface
{
$this->osmLogo = $osmLogo;
return $this;
}
public function isUseTileCache(): bool
{
return $this->useTileCache;
}
public function setUseTileCache(bool $useTileCache): PrinterInterface
{
$this->useTileCache = $useTileCache;
return $this;
}
public function getZoom(): int
{
return $this->zoom;
}
public function setZoom(int $zoom): PrinterInterface
{
$this->zoom = $zoom;
return $this;
}
public function getLatitude(): float
{
return $this->latitude;
}
public function setLatitude(float $latitude): PrinterInterface
{
$this->latitude = $latitude;
return $this;
}
public function getLongitude(): float
{
return $this->longitude;
}
public function setLongitude(float $longitude): PrinterInterface
{
$this->longitude = $longitude;
return $this;
}
public function getWidth(): int
{
return $this->width;
}
public function setWidth($width): PrinterInterface
{
$this->width = $width;
return $this;
}
public function getHeight(): int
{
return $this->height;
}
public function setHeight($height): PrinterInterface
{
$this->height = $height;
return $this;
}
public function getImage()
{
return $this->image;
}
public function setImage($image): PrinterInterface
{
$this->image = $image;
return $this;
}
public function getMaptype(): string
{
return $this->maptype;
}
public function setMaptype(string $maptype): PrinterInterface
{
$this->maptype = $maptype;
return $this;
}
public function getCenterX(): int
{
return $this->centerX;
}
public function setCenterX($centerX): PrinterInterface
{
$this->centerX = $centerX;
return $this;
}
public function getCenterY(): int
{
return $this->centerY;
}
public function setCenterY(int $centerY): PrinterInterface
{
$this->centerY = $centerY;
return $this;
}
public function getOffsetX(): int
{
return $this->offsetX;
}
public function setOffsetX(int $offsetX): PrinterInterface
{
$this->offsetX = $offsetX;
return $this;
}
public function getOffsetY(): int
{
return $this->offsetY;
}
public function setOffsetY(int $offsetY): PrinterInterface
{
$this->offsetY = $offsetY;
return $this;
}
public function getMarkers(): array
{
return $this->markers;
}
public function setMarkers(array $markers): PrinterInterface
{
$this->markers = $markers;
return $this;
}
public function getPolylines(): array
{
return $this->polylines;
}
public function setPolylines(array $polylines): PrinterInterface
{
$this->polylines = $polylines;
return $this;
}
}

208
src/Printer/Printer.php Normal file
View File

@ -0,0 +1,208 @@
<?php
namespace StaticMapLite\Printer;
use StaticMapLite\Canvas\Canvas;
use StaticMapLite\CanvasTilePainter\CanvasTilePainter;
use StaticMapLite\CopyrightPrinter\CopyrightPrinter;
use StaticMapLite\Element\Marker\AbstractMarker;
use StaticMapLite\Element\Polyline\Polyline;
use StaticMapLite\ElementPrinter\Marker\ExtraMarkerPrinter;
use StaticMapLite\ElementPrinter\Polyline\PolylinePrinter;
use StaticMapLite\MapCache\MapCache;
use StaticMapLite\Output\CacheOutput;
use StaticMapLite\Output\ImageOutput;
use StaticMapLite\TileResolver\CachedTileResolver;
use StaticMapLite\Util;
class Printer extends AbstractPrinter
{
public function __construct()
{
$this->zoom = 0;
$this->latitude = 0;
$this->longitude = 0;
$this->width = 500;
$this->height = 350;
$this->maptype = $this->tileDefaultSrc;
$this->mapCache = new MapCache($this);
$this->tileResolver = new CachedTileResolver();
$this->tileResolver->setTileLayerUrl($this->tileSrcUrl[$this->maptype]);
}
public function addMarker(AbstractMarker $marker): Printer
{
$this->markers[] = $marker;
return $this;
}
public function addPolyline(Polyline $polyline): Printer
{
$this->polylines[] = $polyline;
return $this;
}
public function setCenter(float $latitude, float $longitude): Printer
{
$this->latitude = $latitude;
$this->longitude = $longitude;
return $this;
}
public function setSize(int $width, int $height): Printer
{
$this->width = $width;
$this->height = $height;
if ($this->width > $this->maxWidth) {
$this->width = $this->maxWidth;
}
if ($this->height > $this->maxHeight) {
$this->height = $this->maxHeight;
}
return $this;
}
public function setZoom(int $zoom): PrinterInterface
{
$this->zoom = $zoom;
if ($this->zoom > 18) {
$this->zoom = 18;
}
return $this;
}
public function setMapType(string $mapType): PrinterInterface
{
$this->maptype = $mapType;
$this->tileResolver->setTileLayerUrl($this->tileSrcUrl[$this->maptype]);
return $this;
}
public function initCoords(): Printer
{
$this->centerX = Util::lonToTile($this->longitude, $this->zoom);
$this->centerY = Util::latToTile($this->latitude, $this->zoom);
$this->offsetX = floor((floor($this->centerX) - $this->centerX) * $this->tileSize);
$this->offsetY = floor((floor($this->centerY) - $this->centerY) * $this->tileSize);
return $this;
}
public function createBaseMap(): Printer
{
$this->canvas = new Canvas(
$this->width,
$this->height,
$this->zoom,
$this->centerX,
$this->centerY
);
$ctp = new CanvasTilePainter();
$ctp
->setCanvas($this->canvas)
->setTileResolver($this->tileResolver)
->paint()
;
return $this;
}
public function placeMarkers(): Printer
{
$printer = new ExtraMarkerPrinter();
foreach ($this->markers as $marker) {
$printer
->setMarker($marker)
->paint($this->canvas)
;
}
return $this;
}
public function placePolylines(): Printer
{
$printer = new PolylinePrinter();
/** @var Polyline $polyline */
foreach ($this->polylines as $polyline) {
$printer
->setPolyline($polyline)
->paint($this->canvas)
;
}
return $this;
}
public function makeMap(): Printer
{
$this->initCoords();
$this->createBaseMap();
if (count($this->polylines)) {
$this->placePolylines();
}
if (count($this->markers)) {
$this->placeMarkers();
}
$this->printCopyright();
return $this;
}
protected function printCopyright(): Printer
{
$cp = new CopyrightPrinter();
$cp
->setCanvas($this->canvas)
->printCopyright()
;
return $this;
}
public function showMap()
{
if ($this->mapCache) {
if (!$this->mapCache->checkMapCache()) {
$this->makeMap();
$this->mapCache->cache($this->canvas);
} else {
$output = new CacheOutput();
$output
->setFilename($this->mapCache->getFilename())
->sendHeader()
->sendImage()
;
}
} else {
$this->makeMap();
$output = new ImageOutput();
$output
->setImage($this->image)
->sendHeader()
->sendImage()
;
}
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace StaticMapLite\Printer;
use StaticMapLite\Canvas\CanvasInterface;
use StaticMapLite\TileResolver\TileResolverInterface;
interface PrinterInterface
{
public function getMaxWidth(): int;
public function setMaxWidth(int $maxWidth): PrinterInterface;
public function getMaxHeight(): int;
public function setMaxHeight(int $maxHeight): PrinterInterface;
public function getTileResolver(): TileResolverInterface;
public function setTileResolver(TileResolverInterface $tileResolver): PrinterInterface;
public function getCanvas(): CanvasInterface;
public function setCanvas(CanvasInterface $canvas): PrinterInterface;
public function getTileSize(): int;
public function setTileSize(int $tileSize): PrinterInterface;
public function getTileSrcUrl(): array;
public function setTileSrcUrl(array $tileSrcUrl): PrinterInterface;
public function getTileDefaultSrc(): string;
public function setTileDefaultSrc(string $tileDefaultSrc): PrinterInterface;
public function getOsmLogo(): string;
public function setOsmLogo(string $osmLogo): PrinterInterface;
public function isUseTileCache(): bool;
public function setUseTileCache(bool $useTileCache): PrinterInterface;
public function getZoom(): int;
public function setZoom(int $zoom): PrinterInterface;
public function getLatitude(): float;
public function setLatitude(float $lat): PrinterInterface;
public function getLongitude(): float;
public function setLongitude(float $lon): PrinterInterface;
public function getWidth(): int;
public function setWidth($width): PrinterInterface;
public function getHeight(): int;
public function setHeight($height): PrinterInterface;
public function getImage();
public function setImage($image): PrinterInterface;
public function getMaptype(): string;
public function setMaptype(string $maptype): PrinterInterface;
public function getCenterX(): int;
public function setCenterX($centerX): PrinterInterface;
public function getCenterY(): int;
public function setCenterY(int $centerY): PrinterInterface;
public function getOffsetX(): int;
public function setOffsetX(int $offsetX): PrinterInterface;
public function getOffsetY(): int;
public function setOffsetY(int $offsetY): PrinterInterface;
public function getMarkers(): array;
public function setMarkers(array $markers): PrinterInterface;
public function getPolylines(): array;
public function setPolylines(array $polylines): PrinterInterface;
}

View File

@ -0,0 +1,32 @@
<?php
namespace StaticMapLite\TileResolver;
use Curl\Curl;
use Imagine\Gd\Imagine;
use Imagine\Image\ImagineInterface;
abstract class AbstractTileResolver implements TileResolverInterface
{
/** @var string $tileLayerUrl */
protected $tileLayerUrl;
/** @var Curl $curl */
protected $curl;
/** @var ImagineInterface $imagine */
protected $imagine;
public function __construct()
{
$this->curl = new Curl();
$this->imagine = new Imagine();
}
public function setTileLayerUrl(string $tileLayerUrl): TileResolverInterface
{
$this->tileLayerUrl = $tileLayerUrl;
return $this;
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace StaticMapLite\TileResolver;
use Imagine\Image\ImageInterface;
class CachedTileResolver extends TileResolver
{
/** @var string $tileCacheBaseDir */
protected $tileCacheBaseDir = '../cache/tiles';
public function fetch(int $zoom, int $x, int $y): ImageInterface
{
$url = $this->resolve($zoom, $x, $y);
$cachedTile = $this->checkTileCache($url);
if ($cachedTile) {
return $cachedTile;
}
$tile = parent::fetch($zoom, $x, $y);
if ($tile) {
$this->writeTileToCache($url, $tile);
}
return $tile;
}
protected function tileUrlToFilename(string $url): string
{
return $this->tileCacheBaseDir . '/' . str_replace(['http://', 'https://'], '', $url);
}
protected function checkTileCache(string $url): ?ImageInterface
{
$filename = $this->tileUrlToFilename($url);
if (file_exists($filename)) {
$tileImagine = $this->imagine->open($filename);
return $tileImagine;
}
return null;
}
protected function writeTileToCache($url, ImageInterface $tileImage): CachedTileResolver
{
$filename = $this->tileUrlToFilename($url);
$this->mkdir_recursive(dirname($filename), 0777);
$tileImage->save($filename);
return $this;
}
protected function mkdir_recursive($pathname, $mode): bool
{
is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode);
return is_dir($pathname) || @mkdir($pathname, $mode);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace StaticMapLite\TileResolver;
use Imagine\Image\ImageInterface;
class TileResolver extends AbstractTileResolver
{
public function resolve(int $zoom, int $x, int $y): string
{
return str_replace(['{z}', '{x}', '{y}'], [$zoom, $x, $y], $this->tileLayerUrl);
}
public function fetch(int $zoom, int $x, int $y): ImageInterface
{
$url = $this->resolve($zoom, $x, $y);
$this->curl->get($url);
$image = $this
->imagine
->load($this->curl->response)
;
return $image;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace StaticMapLite\TileResolver;
use Imagine\Image\ImageInterface;
interface TileResolverInterface
{
public function setTileLayerUrl(string $tileLayerUrl): TileResolverInterface;
public function resolve(int $zoom, int $x, int $y): string;
public function fetch(int $zoom, int $x, int $y): ImageInterface;
}

16
src/Util.php Normal file
View File

@ -0,0 +1,16 @@
<?php
namespace StaticMapLite;
class Util
{
public static function lonToTile(float $longitude, int $zoom): float
{
return (($longitude + 180) / 360) * pow(2, $zoom);
}
public static function latToTile(float $latitude, int $zoom): float
{
return (1 - log(tan($latitude * pi() / 180) + 1 / cos($latitude * pi() / 180)) / pi()) / 2 * pow(2, $zoom);
}
}

View File

@ -1,409 +0,0 @@
<?php
/**
* staticMapLite 0.3.1
*
* Copyright 2009 Gerhard Koch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Gerhard Koch <gerhard.koch AT ymail.com>
*
* USAGE:
*
* staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc
*
*/
error_reporting(0);
ini_set('display_errors', 'off');
Class staticMapLite
{
protected $maxWidth = 1024;
protected $maxHeight = 1024;
protected $tileSize = 256;
protected $tileSrcUrl = array('mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png',
'osmarenderer' => 'http://otile1.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.png',
'cycle' => 'http://a.tile.opencyclemap.org/cycle/{Z}/{X}/{Y}.png',
);
protected $tileDefaultSrc = 'mapnik';
protected $markerBaseDir = 'images/markers';
protected $osmLogo = 'images/osm_logo.png';
protected $markerPrototypes = array(
// found at http://www.mapito.net/map-marker-icons.html
'lighblue' => array('regex' => '/^lightblue([0-9]+)$/',
'extension' => '.png',
'shadow' => false,
'offsetImage' => '0,-19',
'offsetShadow' => false
),
// openlayers std markers
'ol-marker' => array('regex' => '/^ol-marker(|-blue|-gold|-green)+$/',
'extension' => '.png',
'shadow' => '../marker_shadow.png',
'offsetImage' => '-10,-25',
'offsetShadow' => '-1,-13'
),
// taken from http://www.visual-case.it/cgi-bin/vc/GMapsIcons.pl
'ylw' => array('regex' => '/^(pink|purple|red|ltblu|ylw)-pushpin$/',
'extension' => '.png',
'shadow' => '../marker_shadow.png',
'offsetImage' => '-10,-32',
'offsetShadow' => '-1,-13'
),
// http://svn.openstreetmap.org/sites/other/StaticMap/symbols/0.png
'ojw' => array('regex' => '/^bullseye$/',
'extension' => '.png',
'shadow' => false,
'offsetImage' => '-20,-20',
'offsetShadow' => false
)
);
protected $useTileCache = true;
protected $tileCacheBaseDir = '../cache/tiles';
protected $useMapCache = true;
protected $mapCacheBaseDir = '../cache/maps';
protected $mapCacheID = '';
protected $mapCacheFile = '';
protected $mapCacheExtension = 'png';
protected $zoom, $lat, $lon, $width, $height, $markers, $image, $maptype;
protected $centerX, $centerY, $offsetX, $offsetY;
public function __construct()
{
$this->zoom = 0;
$this->lat = 0;
$this->lon = 0;
$this->width = 500;
$this->height = 350;
$this->markers = array();
$this->maptype = $this->tileDefaultSrc;
}
public function parseParams()
{
global $_GET;
if (!empty($_GET['show'])) {
$this->parseOjwParams();
}
else {
$this->parseLiteParams();
}
}
public function parseLiteParams()
{
// get zoom from GET paramter
$this->zoom = $_GET['zoom'] ? intval($_GET['zoom']) : 0;
if ($this->zoom > 18) $this->zoom = 18;
// get lat and lon from GET paramter
list($this->lat, $this->lon) = explode(',', $_GET['center']);
$this->lat = floatval($this->lat);
$this->lon = floatval($this->lon);
// get size from GET paramter
if ($_GET['size']) {
list($this->width, $this->height) = explode('x', $_GET['size']);
$this->width = intval($this->width);
if ($this->width > $this->maxWidth) $this->width = $this->maxWidth;
$this->height = intval($this->height);
if ($this->height > $this->maxHeight) $this->height = $this->maxHeight;
}
if (!empty($_GET['markers'])) {
$markers = explode('|', $_GET['markers']);
foreach ($markers as $marker) {
list($markerLat, $markerLon, $markerType) = explode(',', $marker);
$markerLat = floatval($markerLat);
$markerLon = floatval($markerLon);
$markerType = basename($markerType);
$this->markers[] = array('lat' => $markerLat, 'lon' => $markerLon, 'type' => $markerType);
}
}
if ($_GET['maptype']) {
if (array_key_exists($_GET['maptype'], $this->tileSrcUrl)) $this->maptype = $_GET['maptype'];
}
}
public function parseOjwParams()
{
$this->lat = floatval($_GET['lat']);
$this->lon = floatval($_GET['lon']);
$this->zoom = intval($_GET['z']);
$this->width = intval($_GET['w']);
if ($this->width > $this->maxWidth) $this->width = $this->maxWidth;
$this->height = intval($_GET['h']);
if ($this->height > $this->maxHeight) $this->height = $this->maxHeight;
if (!empty($_GET['mlat0'])) {
$markerLat = floatval($_GET['mlat0']);
if (!empty($_GET['mlon0'])) {
$markerLon = floatval($_GET['mlon0']);
$this->markers[] = array('lat' => $markerLat, 'lon' => $markerLon, 'type' => "bullseye");
}
}
}
public function lonToTile($long, $zoom)
{
return (($long + 180) / 360) * pow(2, $zoom);
}
public function latToTile($lat, $zoom)
{
return (1 - log(tan($lat * pi() / 180) + 1 / cos($lat * pi() / 180)) / pi()) / 2 * pow(2, $zoom);
}
public function initCoords()
{
$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);
}
public function createBaseMap()
{
$this->image = imagecreatetruecolor($this->width, $this->height);
$startX = floor($this->centerX - ($this->width / $this->tileSize) / 2);
$startY = floor($this->centerY - ($this->height / $this->tileSize) / 2);
$endX = ceil($this->centerX + ($this->width / $this->tileSize) / 2);
$endY = ceil($this->centerY + ($this->height / $this->tileSize) / 2);
$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;
for ($x = $startX; $x <= $endX; $x++) {
for ($y = $startY; $y <= $endY; $y++) {
$url = str_replace(array('{Z}', '{X}', '{Y}'), array($this->zoom, $x, $y), $this->tileSrcUrl[$this->maptype]);
$tileData = $this->fetchTile($url);
if ($tileData) {
$tileImage = imagecreatefromstring($tileData);
} else {
$tileImage = imagecreate($this->tileSize, $this->tileSize);
$color = imagecolorallocate($tileImage, 255, 255, 255);
@imagestring($tileImage, 1, 127, 127, 'err', $color);
}
$destX = ($x - $startX) * $this->tileSize + $this->offsetX;
$destY = ($y - $startY) * $this->tileSize + $this->offsetY;
imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize);
}
}
}
public function placeMarkers()
{
// loop thru marker array
foreach ($this->markers as $marker) {
// set some local variables
$markerLat = $marker['lat'];
$markerLon = $marker['lon'];
$markerType = $marker['type'];
// clear variables from previous loops
$markerFilename = '';
$markerShadow = '';
$matches = false;
// check for marker type, get settings from markerPrototypes
if ($markerType) {
foreach ($this->markerPrototypes as $markerPrototype) {
if (preg_match($markerPrototype['regex'], $markerType, $matches)) {
$markerFilename = $matches[0] . $markerPrototype['extension'];
if ($markerPrototype['offsetImage']) {
list($markerImageOffsetX, $markerImageOffsetY) = explode(",", $markerPrototype['offsetImage']);
}
$markerShadow = $markerPrototype['shadow'];
if ($markerShadow) {
list($markerShadowOffsetX, $markerShadowOffsetY) = explode(",", $markerPrototype['offsetShadow']);
}
}
}
}
// check required files or set default
if ($markerFilename == '' || !file_exists($this->markerBaseDir . '/' . $markerFilename)) {
$markerIndex++;
$markerFilename = 'lightblue' . $markerIndex . '.png';
$markerImageOffsetX = 0;
$markerImageOffsetY = -19;
}
// create img resource
if (file_exists($this->markerBaseDir . '/' . $markerFilename)) {
$markerImg = imagecreatefrompng($this->markerBaseDir . '/' . $markerFilename);
} else {
$markerImg = imagecreatefrompng($this->markerBaseDir . '/lightblue1.png');
}
// check for shadow + create shadow recource
if ($markerShadow && file_exists($this->markerBaseDir . '/' . $markerShadow)) {
$markerShadowImg = imagecreatefrompng($this->markerBaseDir . '/' . $markerShadow);
}
// calc position
$destX = floor(($this->width / 2) - $this->tileSize * ($this->centerX - $this->lonToTile($markerLon, $this->zoom)));
$destY = floor(($this->height / 2) - $this->tileSize * ($this->centerY - $this->latToTile($markerLat, $this->zoom)));
// copy shadow on basemap
if ($markerShadow && $markerShadowImg) {
imagecopy($this->image, $markerShadowImg, $destX + intval($markerShadowOffsetX), $destY + intval($markerShadowOffsetY),
0, 0, imagesx($markerShadowImg), imagesy($markerShadowImg));
}
// copy marker on basemap above shadow
imagecopy($this->image, $markerImg, $destX + intval($markerImageOffsetX), $destY + intval($markerImageOffsetY),
0, 0, imagesx($markerImg), imagesy($markerImg));
};
}
public function tileUrlToFilename($url)
{
return $this->tileCacheBaseDir . "/" . str_replace(array('http://'), '', $url);
}
public function checkTileCache($url)
{
$filename = $this->tileUrlToFilename($url);
if (file_exists($filename)) {
return file_get_contents($filename);
}
}
public function checkMapCache()
{
$this->mapCacheID = md5($this->serializeParams());
$filename = $this->mapCacheIDToFilename();
if (file_exists($filename)) return true;
}
public function serializeParams()
{
return join("&", array($this->zoom, $this->lat, $this->lon, $this->width, $this->height, serialize($this->markers), $this->maptype));
}
public function mapCacheIDToFilename()
{
if (!$this->mapCacheFile) {
$this->mapCacheFile = $this->mapCacheBaseDir . "/" . $this->maptype . "/" . $this->zoom . "/cache_" . substr($this->mapCacheID, 0, 2) . "/" . substr($this->mapCacheID, 2, 2) . "/" . substr($this->mapCacheID, 4);
}
return $this->mapCacheFile . "." . $this->mapCacheExtension;
}
public function mkdir_recursive($pathname, $mode)
{
is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode);
return is_dir($pathname) || @mkdir($pathname, $mode);
}
public function writeTileToCache($url, $data)
{
$filename = $this->tileUrlToFilename($url);
$this->mkdir_recursive(dirname($filename), 0777);
file_put_contents($filename, $data);
}
public function fetchTile($url)
{
if ($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached;
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0");
curl_setopt($ch, CURLOPT_URL, $url);
$tile = curl_exec($ch);
curl_close($ch);
if ($tile && $this->useTileCache) {
$this->writeTileToCache($url, $tile);
}
return $tile;
}
public function copyrightNotice()
{
$logoImg = imagecreatefrompng($this->osmLogo);
imagecopy($this->image, $logoImg, imagesx($this->image) - imagesx($logoImg), imagesy($this->image) - imagesy($logoImg), 0, 0, imagesx($logoImg), imagesy($logoImg));
}
public function sendHeader()
{
header('Content-Type: image/png');
$expires = 60 * 60 * 24 * 14;
header("Pragma: public");
header("Cache-Control: maxage=" . $expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
}
public function makeMap()
{
$this->initCoords();
$this->createBaseMap();
if (count($this->markers)) $this->placeMarkers();
if ($this->osmLogo) $this->copyrightNotice();
}
public function showMap()
{
$this->parseParams();
if ($this->useMapCache) {
// use map cache, so check cache for map
if (!$this->checkMapCache()) {
// map is not in cache, needs to be build
$this->makeMap();
$this->mkdir_recursive(dirname($this->mapCacheIDToFilename()), 0777);
imagepng($this->image, $this->mapCacheIDToFilename(), 9);
$this->sendHeader();
if (file_exists($this->mapCacheIDToFilename())) {
return file_get_contents($this->mapCacheIDToFilename());
} else {
return imagepng($this->image);
}
} else {
// map is in cache
$this->sendHeader();
return file_get_contents($this->mapCacheIDToFilename());
}
} else {
// no cache, make map, send headers and deliver png
$this->makeMap();
$this->sendHeader();
return imagepng($this->image);
}
}
}
$map = new staticMapLite();
print $map->showMap();

View File

@ -70,7 +70,7 @@ a.external:after { content: "\2197";}
staticMapLite - simple map for your website
</h2>
<p>
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" width="865" height="512" /></p>
<img src="staticmap.php?center=53.551886,9.992474,&zoom=14&size=865x512&maptype=wikimedia-intl" width="865" height="512" /></p>
<p>
This image was created using the following simple &lt;img> tag:
<pre>&lt;img src="staticmap.php?center=40.714728,-73.998672&amp;zoom=14&amp;size=865x512&amp;maptype=mapnik" /&gt;</pre>
@ -119,4 +119,4 @@ a.external:after { content: "\2197";}
</div>
</div>
</body>
</html>
</html>

7
web/info.php Normal file
View File

@ -0,0 +1,7 @@
<?php
/**
* Created by PhpStorm.
* User: maltehuebner
* Date: 26.05.17
* Time: 15:09
*/

81
web/staticmap.php Normal file
View File

@ -0,0 +1,81 @@
<?php
/**
* staticMapLite 0.3.1
*
* Copyright 2009 Gerhard Koch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Gerhard Koch <gerhard.koch AT ymail.com>
*
* USAGE:
*
* staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc
*
*/
require_once '../vendor/autoload.php';
use StaticMapLite\Element\Factory\Marker\ExtraMarkerFactory;
use StaticMapLite\Element\Polyline\Polyline;
use StaticMapLite\Printer\Printer;
$printer = new Printer();
list($centerLatitude, $centerLongitude) = explode(',', $_GET['center']);
list($width, $height) = explode('x', $_GET['size']);
$printer
->setCenter($centerLatitude, $centerLongitude)
->setZoom($_GET['zoom'])
->setSize($width, $height)
->setMapType($_GET['maptype'])
;
$markers = isset($_GET['markers']) ? $_GET['markers'] : null;
if ($markers) {
$markerList = explode('|', $markers);
$markerFactory = new ExtraMarkerFactory();
foreach ($markerList as $markerData) {
list($markerLatitude, $markerLongitude, $markerShape, $markerColor, $markerIcon) = explode(',', $markerData);
$marker = $markerFactory->create(floatval($markerLatitude), floatval($markerLongitude), $markerShape, $markerColor, $markerIcon);
$printer->addMarker($marker);
}
}
$polylines = isset($_GET['polylines']) ? $_GET['polylines'] : null;
if ($polylines) {
$polylineList = explode('|', $polylines);
foreach ($polylineList as $polylineData) {
list($polyline64String, $colorRed, $colorGreen, $colorBlue) = explode(',', $polylineData);
$polylineString = base64_decode($polyline64String);
$polyline = new Polyline($polylineString, $colorRed, $colorGreen, $colorBlue);
$printer->addPolyline($polyline);
}
}
$printer->showMap();