Клуб API Карт

Получить географические координаты углов тайла

sergeantklin
15 мая 2012, 15:28

Здравствуйте.

Использую TileDataSource. В функции getTileUrl(tile, zoom) получаю географические координаты привязки (левого нижнего угла) тайла:

var worldSize = Math.pow(2.0, zoom);

var equatorLength = 40075016.685578488;

var Rn = 6378137.0;

var a = worldSize / equatorLength;

var b = equatorLength / 2.0;

var MercatorX = tile.x / a - b;

var MercatorY = b - tile.y / a;

var ab = 0.00335655146887969400;

var bb = 0.00000657187271079536;

var cb = 0.00000001764564338702;

var db = 0.00000000005328478445;

var xphi = Math.PI / 2 - 2 * Math.atan(1 / Math.exp(MercatorY / Rn)) ;

var latitude = xphi + ab * Math.sin(2 * xphi) + bb * Math.sin(4 * xphi) + cb * Math.sin(6 * xphi) + db * Math.sin(8 * xphi);

latitude = latitude * 180 / Math.PI;

var longitude = MercatorX * 180 / Math.PI / Rn;

Это работает верно. Но мне нужно еще получить географические координаты правого верхнего угла (или длину тайла по широте и долготе).

Я пробовал следующее:

// получить точку в пикселях, соответствующую правому верхнему углу (при размере тайла 256х256 пикселей)

var mapPixels = map.tileCoordinates.toPixels(tile, new YMaps.Point(256,256), zoom, 256);

// преобразовать полученную точку из пикселей в координаты:

var mapCoords = map.converter.localPixelsToCoordinates(mapPixels);

Широта и долгота получаются неверными (широта всегда равна -90). Наверное, размеры тайла нужно считать в глобальных пикселях, но как это сделать я не знаю. 

Подскажите, куда копать?

 

13 комментариев
Подписаться на комментарии к посту

как вариант - правый верхний угол тайла {x, y} - это левый нижний {x+1, y-1} 

 

нет, не катит. Номера соседних тайлов не следуют один за другим, расположение у них другое.

это как это???

 


Да, тут все верно, я был неправ.

кстати, когда будете делать запрос в мускул, используйте spatial - функции.

запрос типа WHERE (lat BETWEEN llat1 AND lat2) AND (lng BETWEEN  lng 1 AND  lng2) - не оптимизируется обычными индексами по определению.

в postgres тоже есть функции для работы с геоданными.

вообще, поиск намного быстрее делать по тайлам.

хотя, все зависит от количетсва объектов.

Ок, учту

spatial функции в муслуле жутко тупят, потому что работают не только для точки, но и для любых полигонов с дырками.

Хотя и позволяют делать сложные мат расчеты.

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

Второй вариант - материлизовать таблицу с обьектами в сфинкс и искать им(летает)

Третий вариант - использоваться адресацию по дереву разбиения, там будет на выходе одино интовое поле.

я где то у них видел speed-test в котором заявлялось что на 1млн записей тратится менее 1с

1сек? У тебя еще сервер с дубу не рухнул?

На выборку 200 из 12 миллионов записей - менее 30мсек с конектом у меня.

не знаю, видел ли ты вот такую реализацию - http://habrahabr.ru/post/138297/

Как-то очень фантастично, я таких цифер в жизни не видел.

буду перепроверять выкладки

Вообще, достаточно в Вашем коде заменить

var MercatorX = tile.x / a - b;

на

ar MercatorX = (tile.x + 1) / a - b;

Получите правый верхний угол тайла.

Через API это делается так:

(а) нужно перевести номер тайла в пиксели от левого верхнего угла мира. Если тайлы у вас идут стандартной плиткой - то просто умножить на 256.

p = new YMaps.Point(tile.x * 256, tile.y * 256)

(б) добавить смещение внутри тайла, если оно есть. В Вашем случае оно (256, 0). Можно учесть это смещение при получении пиксельных координат:

p = new YMaps.Point(tile.x * 256 + 256, tile.y * 256)

(в) перевести из текущего масштаба в предельный масштаб координатной системы карты (23 по умолчанию):

p = map.tileCoordinates.scale(p, zoom, map.coordSystem.getMaxZoom())

(г) перевести в географические координаты:

geoPoint = map.coordSystem.toCoordPoint(p);

Спасибо большое, проблема решена.