Клуб API Карт

Незначительное смещение карты (решено)

Пост в архиве.

Заметил, что одни и те же дома на разных картах немного "гуляют". Даже оригинальная карта от народной. Планировал подключить 2gis с оригинальной ("yandex#map") вместе. На выбор пользователя. Там различие где-то на ширину дома по "Y".  Т.к. у меня ещё имеется тайловый слой, с огромным количеством меток на домах, забить на это никак не получается. Пересчитывать все тайлы с активными областями под разные карты или ограничить пользователя одной картой очень бы не хотелось. В связи с этим вопрос: возможно ли как-то при подключении слоя карты задавать маленькое (<256px) смещение этой самой карты, что бы максимально подогнать её под "yandex#map" ?

Вот пример:

32 комментария
Sergey Konstantinov
28 января 2016, 02:35
У 2gis другая проекция, укажите в опциях карты projection: ymaps.projection.sphericalMercator

Эх если бы было всё так просто :)

Разумеется уже указано. Если бы не указал смещение было бы не дом, а несколько километров

Sergey Konstantinov
28 января 2016, 02:35
Значит, карты Яндекса и 2гиса этого города физически сдвинуты друг относительно друга. Так бывает :)

да, так и есть. Именно по этому я и ищу возможность 2gis немного сдвинуть. Притом касается это не только 2gis. Если посмотреть даже родные карты "yandex#satellite" или  "yandex#publicMap", то они тоже сдвинуты относительно "yandex#map" поэтому какое-то решение необходимо или метки съезжают

Sergey Konstantinov
28 января 2016, 02:35
Что за город?

Санкт-Петербург. Родной для Яндекса вроде :)

На примере угол Блохина и Кронверкского пр.

А как это может помочь в решении моей проблемы ?

Sergey Konstantinov
28 января 2016, 02:35
Никак :) Но я передам нашим картографам.

Спасибо. Однако не картографы скорее помогут, а разработчики. Карта "yandex#map", как мне кажется, самая правильная. Это у других карт немного не так. Так что было бы хорошо именно сдвиг при подключении сторонних карт (и народной заодно).

Спасибо.

Sergey Konstantinov
28 января 2016, 02:35
Я разработчик :)
Я могу подсказать код, который сдвинет слои, но этот сдвиг будет применяться везде, а не только в Петербруге.
Sergey Konstantinov
28 января 2016, 02:35
К тому же, когда-нибудь карта исправится, и получится сдвиг в другую сторону :)

Приятно, что разработчики активно учавствуют в обсуждении. Я думал что один из нас, смертных :-)

Относительно того, что карта исправится - сильно сомневаюсь. Даже народная рисуется похоже по спутникам и, как следствие, имеет некоторый сдвиг. Подсказать код это конечно заманчиво. А не планируется (случайно вдруг) это реализовать в опциях подключения карты ? Например где-то там же где проекция указывается ? ;-)

Sergey Konstantinov
28 января 2016, 02:35
Скорее всего, спутник (и народная карта) привязаны как раз правильно, а вот карта поставщика смещена относительно истины.
Опцию делать мы не хотим, тут надо подложку исправлять, а не опции вводить. Да и кейс не выглядит популярным - вы первый, кто такое просит :)

я вообще-то новичёк (по части API yandex) и задача у меня не очень-то сложная, но уже столкнулся с этим так что рано или поздно вопрос явно приобритёт популярность. И тут даже не важно кто прав, а кто не очень (хотя где-то тут я читал уже от разработчиков, что именно "схема" правильнее). Главное - нестыковка. Карт разных много. API у вас хороший - мне вот больше остальных понравился, а перед началом проекта я рассматривал внимательно разные API. Так что тут вы молодцы. Используя тайлы эта проблема всплывёт когда-нибудь однозначно т.к. ограничивать одной картой никто не хочет. Мне кажется, что с технической точки зрения реализовать смещение не очень сложно, но будет востребовано именно там, где используют тайлы. Кусок кода тоже пойдёт, если уж "мы не хотим" :-)

 

З.Ы. Да, если даже предположить, что у вас такой поставщик нехороший, то например "народная" смещена относительно 2gis, но почти попадает в openstreetmap, что не мешает всем трём не попадать в родную "схему", а координаты домов мы получаем именно со схемы (как я понял). Вообщем лучше бы смещение :-)

Sergey Konstantinov
28 января 2016, 02:35
Как-то так тогда.
1. Заводим собственную проекцию, смещенную относительно стандартной wgs84:

var offset = [1e-3, 1e-3], // смещение карты на 0-м масштабе, подобрать руками
     myProjection = {
         fromGlobalPixels: function (pixels, zoom) {
              var scale = Math.pow(2, zoom);
              return ymaps.projection.wgs84Mercator.fromGlobalPixels([
                  pixels[0] - offset[0] * scale,
                  pixels[1] - offset[1] * scale
              ], zoom);
         },
         toGlobalPixels: function (coords, zoom) {
              var scale = Math.pow(2, zoom),
                   pixels = ymaps.projection.wgs84Mercator.toGlobalPixels(coords, zoom);
              return [
                  pixels[0] + offset[0] * scale,
                  pixels[1] + offset[1] * scale
              ];
         },
         isCycled: function () { return [true, false] }
     };
2. Создаём свой слой, отнаследованный от yandex#map, но с кастомной проекцией.
var YandexMapLayer = ymaps.layer.storage.get(ymaps.mapType.storage.get('yandex#map').getLayers()[0]),
    MyLayer = function () {
        var l = new YandexMapLayer();
        l.options.set('projection', myProjection);
        return l;
    };
3. Кладём слой в хранилище
ymaps.layer.storage.add('my#layer', MyLayer);
ymaps.mapType.storage.add('my#type', new ymaps.MapType('Яндекс.Карта со смещением', ['my#layer']);
У вас появляется новый тип карты 'my#type' - схема от Яндекса со смещением.

спасибо

большое :-)

 

 var l = new YandexMapLayer();
        l.options.set('projection', myProjection);

а разве проекцию нельзя передать в опциях, во втором параметре в конструктор

Sergey Konstantinov
28 января 2016, 02:35
В яндексовый слой - нет. У него там жестко wgs84 зашит.

Правильно ли я понял, что для сторонних карт мы их обычным способом кладём в хранилище, а потом как в п.2 ? Или же можно его сразу создать с проекцией и засунуть в хранилище ?

Sergey Konstantinov
28 января 2016, 02:35
Со сторонними картами так же, только new Layer(template, options), а не YandexMapLayer()
Проекцию можно сразу в конструкторе указать.

это понятно. Я имел ввиду, что надо ли класть в хранилище, а потом вытаскивать для изменения ? ymaps.layer.storage.get нужен ? Или можно сразу 

var l = new ymaps.Layer("адрес","{projection: myProjection}");

и в моём случае ещё везде меняем projection.wgs84Mercator на projection.sphericalMercator для 2gis ? Я правильно понял ?

Sergey Konstantinov
28 января 2016, 02:35
Если вы таки хотите поправить 2gis, а не яндекс.карту - да.
Sergey Konstantinov
28 января 2016, 02:35
Нет, вытаскивать через get ничего не надо.
Обратите только внимание, что в layer.storage кладутся не экземпляры, а классы (конструкторы) слоёв.

Ок. Попробую. Спасибо большое за помощь и участие в обсуждении - очень выручили

twirl - ты гений! :-)

Всё работает как часы! Возвращаясь к неправильности карт (просто ради интереса) вот какие у меня получились смещения относительно родной схемы (x,y)

2gis: -0.00007,-0.00027

OSM: -0.00007,-0.00008

Google: 0,-0.00015

При этом из за разности объектов на картах совпадение не идеальное, но тут уже ничего  не поделаешь.

Так что складывается впечатление, что "правильной" просто быть не может :-)

Денис Анатольевич
17 января 2018, 07:15
smog005,
Привет, не  мог бы скинуть пример реализации? Не могу найти в документах подключение слоев в апи 2.1

Подскажите пожалуйста, как мне сделать, чтобы на карте были видны все метки, при размещении карты на своем сайте? У меня же метки видны только при нажатии несколько раз  "-"

col = new ymaps.GeoObjectCollection(); // создаём коллекцию

col.add(placemark); //добавляем в неё всё

myMap.setBounds(col.getBounds(),{precizeZoom: true}); // показываем всю коллекцию сразу

как мне это сделать пошагово, вот зашла я в карту, нажала на редактировать, карта готова к редактированию, что дальше или это надо прописывать в самом html коде, тогда что именно прописывать и как? вот мой код карты: 

я привёл пример через html, а не конструктор

напишите код карты не через конструктор) могу помочь если что ;)