Клуб API Карт

Есть ли аналог GeoCollectionBounds в новом API?

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

Собственно сабж.

По крайней мере мне ничего в документации найти не удалось.

Можно конечно самому, но не хочеться изобретать велосипедов.

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

Аналога нет.

Отчасти потому что он не всегда и не всем нужен, а пересчет границ области при добавлении (и особенно при удалении) элементов из коллекции занимает время и, как следствие, коллекции будут работать медленнее, даже если вы не используете этот функционал.

 

То как это (расчет bounds) было реализовано в первом АПИ - неудобно, приходилось "руками" в цикле перекладывать точки из GeoObjectCollection в GeoCollectionBounds.

 

И поскольку во второй версии геометрия объектов представляет собой нативные объекты javascript (массивы), то расчет области коллекции сводится к сравнению и выбору максимальных / минимальных значений координат у элементов коллекции. Кажется что во 2-й версии самым правильным решением этой задачи будет создание отдельного класса, отнаследованного от ymaps.GeoObjectCollection, расширяющего стандартную коллекцию нужными методами.

 

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

>  а пересчет границ области при добавлении (и особенно при удалении) элементов из коллекции занимает время 


Ленивый метод GeoPointsCollection.getBounds() спасает день. В итоге при добавлении/удалении все сводится к this.bounds = undefined;

вам придется тогда каждый раз при вызове getBounds перебирать все элементы коллекции

это дорого

Ключевое словосочетание "Ленивый метод" (lazy method).

 

Иными словами:

getBounds:function() {

    if(!this.__bounds) {

        this.__bounds = this.__calculateBounds();

    }

 

    return this.__bounds;

}

А при добавлении/удалении элемента коллекции делать delete this.__bounds;

да понятно что ленивый,

но этот вариант подразумевает что при добавлении/удалении элемента,

если потом спросить bounds  коллекции его придется заного пересчитать, что дорого.

Второй минус, - как узнать что bounds коллекции изменился?

 

Моя реализация - оптимальная золотая середина

При добавлении элемента она не делает delete

а просто проверяет выходят ли координаты нового элемента за bounds коллекции и если нет, то ничего не делает, а если да, расширяет bounds коллекции до координат элемента и кидает "boundschange" (стандартное событие в API) и это на самом деле дешево.

 

А вот с удалением тут есть проблема, поскольку если удаляемый элемент находится "скраю" т.е. учавствует в формировании bounds коллекции то нужно ПОЛНОСТЬЮ пересчитать bounds т.к. неизвестно какой у коллекции bounds без этого элемента. Но на самом деле кейс удаления элементов из коллекции более редкий, чем добавление,

если же он не "на краю" а "всередине", то удаление опять таки будет дешевым.

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

 

Кстати вариант с удалением решается просто, если точка участвует в крайних значениях - пересчитываем полностью, те

 

if (bounds.topLat == point.lat || bounds.topLon == point.lon || bounds.bottomLat == point.lat || bounds.bottomLon == point.lon) { пересчитываем все }

ну это зависит от кейса использования.

и оверхед в случае отсутствия необходимости полного пересчета (редкие кейсы удаления) минимален

 

к тому же я не понимаю зачем пересчитывать bounds если он не изменился,

и как узнавать что bounds изменился

Так bounds и не нужно пересчитывать каждый раз.

Он кешируется ленивым методом.

А изменение коллекции сбрасывает bounds и заставляет его просчитать заново при следующем вызове getBounds