Клуб API Карт

Окружность заданного радиуса вокруг добавляемых объектов

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

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

30 комментариев

Смотрите метод contains у геометрии окружности

Благодарю!

Вы можете вместе с меткой добавлять окружность с таким же центром и радиусом в 10км http://trunk.ogorbacheva.apidev.yandex.ru/maps/doc/jsapi/2.x/ref/reference/Circle.xml, если хотите отслеживать визуально. Также можно программно проверять, не попадают ли объекты в круг через метод contains геометрии, как и написал бабушка-бэтмен.

Спасибо! Мне как раз нужно добавлять вместе с меткой окружность с таким же центром и радиусом в 10 км. Ссылка к сожалению не открывается. Можно какой-нибудь материал, как это сделать?

извините, дала ссылку на внутренний ресурс http://api.yandex.ru/maps/doc/jsapi/2.x/ref/reference/Circle.xml

 

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

Подскажите, пожалуйста, как можно такое организовать?

Спасибо  

Есть 2 пути решения.

Вариант №1 (простой, но не очень красивый архитектурно).

Слушать на метках событие mapchange.  При добавлении метки на карту добавлять на карту соответствующий ей оверлей круга.

Вариант №2 (красивый архитектурно, но надо постараться).

1. Реализовать объект IOverlayFactory и передавать его через опции в ваши метки.

2. Этот  IOverlayFactory должен создавать объект IOverlay. Этот объект, в свою очередь, реально будет состоять из двух разных оверлеев - оверлея метки и круга.

 

 Спасибо за оперативный ответ, но я не нашел как воспользоваться - overlay.staticGraphics.Circle. Подскажите пожалуйста, можно коротеньким примерчиком.

 

Спасибо  

// Создадим пиксельную геометрию. В качестве центра окружности возьмем пиксельную геометрию метки, к которой привязан круг.

var geometry = new ymaps.geometry.pixel.Circle(placemark.geometry.getPixelGeometry().getCoordinates(), radius),

     overlay = new ymaps.overlay.staticGraphics.Circle(geometry, null, {fillColor: "#cccccc"});

overlay.setMap(myMap);

 

// Удалять с карты соответственно overlay.setMap(null);

 

Спасибо за ответ, получилось, но есть проблема - радиус число не постоянное, а зависит от масштаба карты, так как подразумевается, что, например, окружность диаметра километр, и при уменьшении масштаба и он будет уменьшаться, и наоборот. Не могу понять зависимость, между радиусом и масштабом.

Может есть лаконичное решение данного вопроса?

 Спасибо 

 

 

 

 

можно вместо оверлея добавлять обычный круг.

http://api.yandex.ru/maps/doc/jsapi/2.x/ref/reference/Circle.xml

В документации как раз описан пример геодезического круга (который меняет радиус в зависимости от координаты центра).

Тогда мы возвращаемся на то, с чего начали - этот объект будет учавствовать в кластере(

Почему? Не добавляйте объект в кластеризатор и не будет участвовать

 Идея та же, что с оверлеем - добавлять окружность только если метка на карте и удалять, если метка удалена с карты. Метка в кластеризаторе, а круг нет.

Получается мне нужно создать\удалить объект круга, только в момент перехода из состояние когда он был не видим и стал и на оборот, при других случаях, когда и был виден и сейчас видим и не было видно и сейчас не видно - ничего не делать. Как я могу в коллбэк ф-и события mapchange отследить эти переходы?

placemark.events.add('mapchange', checkVisibility);

var placemarkMonitor = new ymaps.Monitor(placemark.options)

         .add('visible', checkVisibility);

function checkVisibility () {

    var newVisible = placemark.getMap() && placemark.options.get('visible', true);

    .....

});

Хранить старые значения можно прямо в объекте, например писать ему какие-то флаги прямо в properties.

Вы можете писать ссылку на создаваемый круг в properties геообъекта и по признаку наличия круга будете знать, в каком состоянии был объект до изменений.

 

Вроде не точно Вы написали. У Вас один и тот же обработчик на изменение карты и на изменение пропертиса. Необходимо: при изменении карты проверять фактическую видимость, и менять в зависимости от текущего состояния и предыдущего, и при изменении этого пропертиса должно рисоваться или удаляться объект круга.

Но как то не стабильно работают добавление пропертиса и дальнейшая работа с ней.

Я его создаю через монитор, потом пытаюсь считать через get, что дает undefined и последующая установка его через set вообще убирает объект placemark с карты.

Уже мозг потихоньку разжижается...

 

 

А вообще очень не хватает шатной возможности организовать радис покрытия объекта! 

 

 

 

 

 

 

Вот рабочий код.

Я слушаю поле visible, чтобы круг скрывался, если метке выставляют опцию visible: false

 

function getCheckVisibility (geoObject) {

        return function () {

            var newVisible = geoObject.getMap() && geoObject.options.get('visible', true);

            if (newVisible && !geoObject.properties.get('circle')) {

                var circle = new ymaps.Circle([geoObject.geometry.getCoordinates(), 1000]);

                 myMap.geoObjects.add(circle);

                 geoObject.properties.set('circle', circle);

            }    

            if (!newVisible && geoObject.properties.get('circle')) {

 myMap.geoObjects.remove(geoObject.properties.get('circle'));

                geoObject.properties.unset('circle');

            }

        }

    }

    // Тут как раз должен быть ваш массив геообъектов.

    for (var i = 0, l = geoObjects.length; i < l; i++) {

        var checkVisibility = getCheckVisibility(geoObjects[i]);

        geoObjects[i].events.add('mapchange', checkVisibility);

        var monitor = new ymaps.Monitor(geoObjects[i].options)

            .add('visible', checkVisibility);

    }

Спасибо большое, получилось!

Я сам примерно до такого же варианта дошел, но не таким локаничным и без хранения объекта круга в пропертисах, а у Вас оптимально и лаконично. Спасибо, осталось только подпилить под массив геообъектов.

 

 

ура)

Интересует теперь как мне можно рефрешить карту с соответствующим вызовом события mapchange, конкретно метода такого не нашел.

 

Спасибо

Что вы имеете в виду под "рефрешить карту"?

 Пременимо к моей задаче вопрос снимается, но все таки есть возможность обновить карту. Например,  какие то объекты изменились, а карта не перерисовалась, и что бы вручную инициировать это, я должен сделать....

 

 Пропущенное вставить)

 

Что значит объекты изменились, а карта не перерисовалась? Что за изменения?

Ну да, всякое бывает. Например, у меня ситуация следующая - карта находится на вкладке и при переходе на эту вкладку, карта не перерисовывается, а просто серый блок, и на данным момент я перерисовываю ее вот так myMap.container.fitToViewport(), но это кастыль. Нет ли какого то специально для этого целей метода? И он мог бы как раз пригодится для моего случая для перерисовки с зоной покрытия и без нее по события mapchange, который вызывается для всех видимых объектов на карте. Это можно сделать проходом по всем объектам в ручную, но это не то...

Это не костыль - это специальный метод для таких целей)

Но в моем случаи он не работает! То есть не происходит перерисование объектов. Но он подходит под случай описанный выше по поводу вкладок(табов). Может есть возможность как то симулировать обновление всей карты и соответсвенно с входящими в нее объектами?

Спасибо

 

 

По идее после вызова fitToViewport должны измениться размеры карты, бросится событие boundschange и все пересчитается. Можете кинуть ссылку на страницу, где можно посмотреть ошибку при перестроении?

К сожалению, она локальная, не в паблике. Но ошибка такая при использовании jquery.tabs. и если карта находится при загрузке старницы на невидимом табе то при переходе на него та мпросто серый див без карты.

  Заведите на это отдельный топик в клубе. Мне кажется, что-то похожее уже обсуждалось.