/** * @return float */ public function getTileSize() { $size = TileStorageInterface::TILE_SIZE; if ($this->zoom > $this->maxZoom) { $size = $this->proj->scale($this->zoom) / $this->proj->scale($this->maxZoom) * $size; } return $size; }
/** * Draw same type to labels (area, region, etc) into tiles * * @param int $zoom * @param Label[] $labels * @param array $style * @param bool $withIcon * * @throws \RuntimeException */ protected function processLabels($zoom, $labels, $style, $withIcon) { $scale = $this->proj->scale($zoom); $count = count($labels); foreach ($labels as $id => $label) { $mem = memory_get_usage(); if (!isset($label->text[$this->lang])) { throw new \RuntimeException("Missing translation ({$this->lang}), abort"); } // center point in grid $point = new Point($label->point->x * $scale, $label->point->y * $scale); $text = $label->text[$this->lang]; // center tile $txHome = floor($point->x / TileStorageInterface::TILE_SIZE); $tyHome = floor($point->y / TileStorageInterface::TILE_SIZE); $this->info("[{$mem}] + ({$zoom}) ({$count}) [{$txHome}, {$tyHome}], {$text}, [K\r"); --$count; // label position relative to tile $cx = $point->x - $txHome * TileStorageInterface::TILE_SIZE; $cy = $point->y - $tyHome * TileStorageInterface::TILE_SIZE; $this->debug("+ ({$id}:{$text}) {$point} ({$txHome}, {$tyHome}) -> cx/cy [{$cx}, {$cy}]\n"); $bbox = $this->getTextDimensions($style, $text); $tileBounds = $this->getTileBounds($point, $bbox); // 1x1 tile will give 0/0 as width/height $xTiles = $tileBounds->getWidth() + 1; $yTiles = $tileBounds->getHeight() + 1; $tx1 = $tileBounds->left; $ty1 = $tileBounds->top; // work image $canvas = $this->createTile($xTiles * TileStorageInterface::TILE_SIZE, $yTiles * TileStorageInterface::TILE_SIZE); // load tiles that needs to be modified $this->loadCanvas($canvas, $zoom, $tx1, $ty1, $xTiles, $yTiles); // label position relative to canvas $p = new Point($cx + ($txHome - $tx1) * TileStorageInterface::TILE_SIZE, $cy + ($tyHome - $ty1) * TileStorageInterface::TILE_SIZE); if ($withIcon) { $this->drawIcon($canvas, $p); } if ($style['fontSize'] > 0) { $this->drawText($canvas, $p, $style, $text, $label->color); } // now save those tiles back $this->saveCanvas($canvas, $zoom, $tx1, $ty1, $xTiles, $yTiles); imagedestroy($canvas); } }
/** * @return int */ private function getBoundsZoom() { $zoom = $this->autoMaxZoom; // area in pixels that markers/polygons occupy $w = $this->bounds->getWidth(); $h = $this->bounds->getHeight(); // map image size in pixels while ($zoom > 1) { $scale = $this->proj->scale($zoom); $newW = (int) ($w * $scale + $this->hMargin); $newH = (int) ($h * $scale + $this->vMargin); if ($newW < $this->width && $newH < $this->height) { break; } $zoom--; } return $zoom; }
/** * @param int $zoom * @param float $expected * * @dataProvider zoomScaleProvider */ public function testScale($zoom, $expected) { $mod = $this->proj->scale($zoom); $this->assertEquals($expected, $mod); }
/** * @param resource $mapImage * @param int $zoom * @param int $mapImageWidth * @param int $mapImageHeight * @param Bounds $zoneBounds */ protected function mapCutter($mapImage, $zoom, $mapImageWidth, $mapImageHeight, $zoneBounds) { // map image coords at base zoom $zoneLeft = $zoneBounds->left; $zoneBottom = $zoneBounds->bottom; $zoneRight = $zoneBounds->right; $zoneTop = $zoneBounds->top; $this->info("[K"); $zoomScale = $this->projWorld->scale($zoom); // coords at current zoom level $left = $zoneLeft * $zoomScale; $bottom = $zoneBottom * $zoomScale; $right = $zoneRight * $zoomScale; $top = $zoneTop * $zoomScale; $width = $right - $left; $height = $bottom - $top; $scaleWidth = $mapImageWidth / $width; $scaleHeight = $mapImageHeight / $height; $this->debug("({$zoom}) map size ({$width}, {$height}), scaled (%.3f, %.3f)\n", $scaleWidth, $scaleHeight); // tiles this image lands $leftTile = floor($left / TileStorageInterface::TILE_SIZE); $topTile = floor($top / TileStorageInterface::TILE_SIZE); // right/bottom are +1 in value // (map on 0,0 tile has 1,1 as right/bottom) as we need top-left coords for that tile $rightTile = ceil($right / TileStorageInterface::TILE_SIZE); $bottomTile = ceil($bottom / TileStorageInterface::TILE_SIZE); $xTiles = $rightTile - $leftTile; $yTiles = $bottomTile - $topTile; $this->debug(" num tiles ({$xTiles}, {$yTiles}), map at ({$left}, {$top}):({$right}, {$bottom}) on tiles({$leftTile}, {$topTile}, %d, %d)\n", $rightTile - 1, $bottomTile - 1); $x1 = 0; $cw = 0; for ($xTile = 0; $xTile < $xTiles; $xTile++) { $y1 = 0; $ch = 0; for ($yTile = 0; $yTile < $yTiles; $yTile++) { $mem = memory_get_usage(); $this->info("[{$mem}] - zoom % 2d (% 5dx% 5d @ %8d grid, mul=%.5f), tile % 3dx% 3d[K\r", $zoom, $width, $height, pow(2, $zoom) * TileStorageInterface::TILE_SIZE, $zoomScale, $xTile, $yTile); // tile coords within grid $tx1 = ($leftTile + $xTile) * TileStorageInterface::TILE_SIZE; $ty1 = ($topTile + $yTile) * TileStorageInterface::TILE_SIZE; $tx2 = ($leftTile + $xTile) * TileStorageInterface::TILE_SIZE + TileStorageInterface::TILE_SIZE; $ty2 = ($topTile + $yTile) * TileStorageInterface::TILE_SIZE + TileStorageInterface::TILE_SIZE; // image padding in tile $pad_l = 0; $pad_t = 0; $pad_r = 0; $pad_b = 0; if ($tx1 < $left) { $pad_l = floor($left - $tx1); } if ($ty1 < $top) { $pad_t = floor($top - $ty1); } if ($tx2 > $right) { $pad_r = ceil($tx2 - $right); } if ($ty2 > $bottom) { $pad_b = ceil($ty2 - $bottom); } $this->debug(">> (xTile:{$xTile}, yTile:{$yTile}): (tx1:{$tx1},ty1:{$ty1}):(tx2:{$tx2},ty2:{$ty2}), padding ({$pad_l}, {$pad_t}):({$pad_r}, {$pad_b})\n"); $dstWidth = TileStorageInterface::TILE_SIZE - $pad_r - $pad_l; $dstHeight = TileStorageInterface::TILE_SIZE - $pad_b - $pad_t; $cw = $dstWidth * $scaleWidth; $ch = $dstHeight * $scaleHeight; $this->debug(">> copy from (%d, %d):(%d,%d) to tile (%d, %d):(%d,%d)\n", $x1, $y1, $cw, $ch, $pad_l, $pad_t, $dstWidth, $dstHeight); $out = $this->loadTileImage($zoom, $leftTile + $xTile, $topTile + $yTile); imagecopyresampled($out, $mapImage, $pad_l, $pad_t, $x1, $y1, $dstWidth, $dstHeight, $cw, $ch); if ($this->debug) { $c = imagecolorallocatealpha($out, 255, 0, 0, 50); imagerectangle($out, $pad_l, $pad_t, $pad_l + $dstWidth, $pad_t + $dstHeight, $c); } $this->saveTileImage($zoom, $leftTile + $xTile, $topTile + $yTile, $out); $y1 += $ch; } $x1 += $cw; } }