Добавить собственную карту не так сложно, как может показаться :). Земля в
Google Maps разворачивается в

проекцию Меркатора
– т.е. представляет собой развёрнутый на плоскость
цилиндр, что даёт нам прямоугольник, который разбивается на маленькие квадратики
(tiles) с размерами 256×256 пикселей.

Пример кусочка карты от Google:


http://mt1.google.com/mt?v=ap.88&hl=ru&x=285&y=162&z=9&s=G

Здесь можно увидеть следующие значения — x=285 y=162 zoom=9, т.е. нам нужно
хранить свою картинку по кусочкам вида tile_285_162_9.jpg (или, разумеется,
аналогичным образом хранить изображения в БД).

Чтобы описать кусочек карты нужно знать три числа:

1 – его номер по вертикали (числа растут сверху вниз (т.е. с севера на юг))
(в примере — 285)
2 – его номер по горизонтали (числа растут справа налево (с запада на восток))
(162)
3 – его уровень увеличения (zoom) (9)

Таким образом карту можно представить в виде стопки слоёв, каждый из которых
состоит из маленьких квадратиков (очевидно, что число квадратиков становится
больше при увеличении уровня приближения).

Итак, у нас есть изображение, которое мы хотим наложить на карту или показать
вместо карты.

Во-первых, нужно узнать те самые три числа, которые дают нам местоположение
нужного кусочка карты.

В самом простом случае можно загрузить нужный нам участок карты и посмотреть
информацию о полученных изображениях (в FireFox: Инструменты->Информация о
странице — > Мультимедиа) или же можно воспользоваться online-сервисом [6].

Там нужно ввести координаты и уровень увеличения интересующего нас места на
карте и он покажет нужные нам числа, но самое интересное — через данный сервис
можно загрузить свою картинку и он её нам разрежет на необходимое количество
кусочков и даст им нужные имена в формате:

Tile_18250_10410_15.jpg

К сожалению, данный сервис вываливается с ошибкой при попытке разрезать
большие картинки. В таком случае — придётся резать картинку самостоятельно.

Следует учесть, что картинку придётся подгонять под те самые квадратики
карты!

Можно воспользоваться Photoshop-ом, я же использую для этих целей Gimp. Чтобы
в нём разрезать картинку нужно по вертикали и горизонтали картинки (уже
подогнанной под карту, т.е. уже обрезанной или смещённой нужным образом) через
каждые 256 пикселей вывести направляющие (Изображение->Направляющие->Новая
направляющая). Далее выполняем преобразование гильотина
(Изображение->Преобразование->Гильотина). После этого у нас появится много
кусочков изображения, которые сохраняются с именами вида:

p4.jpg – исходное изображение
p4-00-00.jpg
p4-01-00.jpg

p4-01-07.jpg
..
p4-09-00.jpg

и т.д.

Нумерация идёт так же как и на карте – первый номер – столбец, второй –
строка. Чтобы переименовать (или лучше сказать – перенумеровать) получившиеся
картинки я написал небольшой скрипт на питоне:

#
# For copy files from def-00-00.jpg to tile\tile_18243_10406_15
#

import os

# for copy
import shutil

srcfile="p4-01-01.JPG"
dstfile=""

#-----------------------------------------
#
# begin here :)
#
print "Start..."

path = srcfile

tilex=281
tiley_beg=160
tiley=tiley_beg
zoom='9'

for i in range(1,10):
for j in range(1,8):
if i<= 9:
x='0'+str(i)
else:
x=str(i)
if j<= 9:
y='0'+str(j)
else:
y=str(j)
srcpath='p4-'+x+'-'+y+'.jpg'
if os.path.exists(srcpath):
print srcpath, ' exists'
shutil.copy(srcpath,'tile\\tile_'+str(tilex)+'_'+str(tiley)+'_'+zoom+'.jpg')
else:
print 'Cant find', srcpath
tiley+=1
tilex+=1
tiley=tiley_beg

print "Done."

В скрипте нужно установить следующие параметры:

  • tilex – номер крайнего изображения по вертикали на карте Google;
  • tiley_beg – номер крайнего изображения по горизонтали на карте Google;
  • zoom – уровень увеличения на карте Google.

Далее изменить граничные условия циклов по количеству ваших полученных
картинок. Не забудьте внести изменения в srcpath, записав туда своё название
картинки. После выполнения скрипта в директории tile будут ваши файлы с именами:

tile_281_160_9.jpg
tile_281_161_9.jpg

tile_289_166_9.jpg

Осталось только настроить вывод вашей карты, средствами Google Maps.

Для приведённого примера:

function add_custom_map(map)
{
var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(57.72883324000875,16.471134185791016),new
GLatLng(49.693182016907464,25.556020736694336) ),8, "Karta39");
var copyrightCollection = new GCopyrightCollection('Map Data:');
copyrightCollection.addCopyright(copyright);

var tilelayers = [new GTileLayer(copyrightCollection , 9, 9)];
tilelayers[0].getTileUrl = CustomGetTileUrl;

tilelayers[0].getCopyright = function(a,b)
{
var c= copyrightCollection.getCopyrightNotice(a,b);
if (!c)
{
c = G_NORMAL_MAP.getTileLayers()[0].getCopyright(a,b);
}
return c;
}

var custommap = new GMapType(tilelayers, new GMercatorProjection(10), "Custom
Map", {shortName:"1645"});

map.addMapType(custommap);
}

function CustomGetTileUrl(a,b)
{
if (b==9 && a.x>280 && a.x<290 && a.y>159 && a.y<167)
return "tile_"+a.x+"_"+a.y+"_"+b+".jpg";
else
return G_NORMAL_MAP.getTileLayers()[0].getTileUrl(a,b);
}

Как видно – сначала создаётся copyright для слоя, а затем сам слой с вашей
картой.

В параметр getTileUrl передаётся функция, возвращающая ваши кусочки карты —
CustomGetTileUrl(a,b), где a – точка с параметрами a.x и a.y, которые указывают
местоположение картинки по вертикали и горизонтали; b – уровень приближения
слоя.

Строчка return G_NORMAL_MAP.getTileLayers()[0].getTileUrl(a,b); возвращает
родную картинку Google Maps – если эту строчку убрать, то на карте будет
отображаться только ваша картинка.

Полный вариант:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Custom Maps</title>
<!-- key for karta39.ru :) -->
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAsL2VORzTwmVBxxfMiMNG7hSQWpIDMILbmlKIxypjOkZkxcl47xRnQ74rU6B3rYRRuou-6ZHLri9jUA"
type="text/javascript"></script>

<script type="text/javascript">
//<![CDATA[

function initialize()
{
if (GBrowserIsCompatible())
{
var map = new GMap2(document.getElementById("map"));
var mmmap = map;
//map.addControl(new GScaleControl());
map.addControl(new GLargeMapControl()); // контрол перемещения и приближения
map.addControl(new GMapTypeControl()); // контрол режима карты
map.setCenter(new GLatLng(54.707168569101256,20.510530471801758),9); //
Kaliningrad
add_custom_map(map);
}
// display a warning if the browser was not compatible
else
{
alert("Sorry, the Google Maps API is not compatible with this browser");
}
}

function add_custom_map(map)
{
var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(57.72883324000875,16.471134185791016),new
GLatLng(49.693182016907464,25.556020736694336) ),8, "Karta39");
var copyrightCollection = new GCopyrightCollection('Map Data:');
copyrightCollection.addCopyright(copyright);

var tilelayers = [new GTileLayer(copyrightCollection , 9, 9)];
tilelayers[0].getTileUrl = CustomGetTileUrl;

tilelayers[0].getCopyright = function(a,b)
{
var c= copyrightCollection.getCopyrightNotice(a,b);
if (!c)
{
c = G_NORMAL_MAP.getTileLayers()[0].getCopyright(a,b);
}
return c;
}

var custommap = new GMapType(tilelayers, new GMercatorProjection(10), "Custom
Map", {shortName:"1645"});

map.addMapType(custommap);
}

function CustomGetTileUrl(a,b)
{
if (b==9 && a.x>280 && a.x<290 && a.y>159 && a.y<167)
return "tile_"+a.x+"_"+a.y+"_"+b+".jpg";
else
return G_NORMAL_MAP.getTileLayers()[0].getTileUrl(a,b);
}
//]]>
</script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>

Посмотреть пример можно здесь:

http://karta39.ru/map/2/cm.html

Стандартная карта:

Включён режим нашей карты:

Т. к. добавлен всего один слой, то и отображается наша карта только при одном
уровне приближения (это видно по ползунку увеличения слева).

Для ознакомления с другими возможностями вывода своих карт можно почитать
[3]. Там показано как сделать так, чтобы ваш слой был полупрозрачным. Для этого
нужно добавить в add_custom_map следующий код:

var paleLayer = new GTileLayer(copyrightCollection,12,12);
paleLayer.getTileUrl = CustomGetTileUrl;
paleLayer.getOpacity = function() {return 0.5}
var tilelayers3 = [G_NORMAL_MAP.getTileLayers()[0], paleLayer];
var custommap3 = new GMapType(tilelayers3, new GMercatorProjection(10), "1645
Mixture", {shortName:"1645Mx"});
mmmap.addMapType(custommap3);

Вот, в принципе, и всё :).

Успехов!

Ссылки

[1]

http://code.google.com/intl/ru_ALL/apis/maps/documentation/reference.html

[2]
http://econym.googlepages.com/index.htm
— Google Maps API Tutorial
[3]
http://econym.googlepages.com/custommap.htm

[4]

http://int2e.com/blog/how-to-make-a-site-like-mapwowcom/

[5]
http://mapki.com/wiki/Automatic_Tile_Cutter

[6]

http://open.atlas.free.fr/GMapsTransparenciesImgOver.php

Оставить мнение

Check Also

Алмазный фонд «Хакера». Самые крутые материалы по реверсингу и malware за три года

Иногда мы, редакторы и авторы «Хакера», сами читаем «Хакер». Нет, ну то есть мы постоянно …