Работа с кластеризованными данными в Maps

Добрый день.

Возник вопрос по картам аддона Maps. Создаю карту с кластеризацией декларативно, добавляю n-количество
элементов на карту через прикрепленный декларативно dataContainer. Сделан отдельный экран с полем поиска по координатам, он ищет в dataContainer похожие точки на карте с такими же координатами и должен вызвать openPopup(), в инструкции описано это действие так

отображение popup
    public void setSelectedGeoObject(PointMap<? extends BaseGeoEntity> pointMap) {
    ((VectorLayer<PointMap>) map.getLayer("pointVectorLayer")).setSelectedGeoObject(pointMap);

    VectorLayer<PointMap> pointMapVectorLayer = map.getLayer("pointVectorLayer");
    Map<?, GeoObjectWrapper<PointMap>> geoObjectWrappersMap = ((WebGeoMap) map).getGeoObjectWrappersMap(pointMapVectorLayer);
    GeoObjectWrapper<PointMap> geoObjectWrapper = geoObjectWrappersMap.get(pointMap.getId());
    if (geoObjectWrapper != null) {
        geoObjectWrapper.openPopup();
    }
}

И оно работает на обычной точке на карте, а с кластеризованной точкой не проходит. В документации не описана работа с кластеризованными данными.

Как можно решить такую задачу ? Определять что это кластеризованная точка и приближать зума карты чтобы декларативно кластер разбивался на точки но я не нашел методов по работе с кластерными точками на карте …

Добрый день!

Из-за особенностей клиент-серверного взаимодействия нельзя выполнить одновременно зум и открытие popup-а. Однако это можно реализовать, используя анимированный зум. Для этого нужно получить доступ ко внутреннему Vaadin-компоненту Leaflet-карты:

@Inject
private GeoMap map;

public void setSelectedGeoObject(PointMap<? extends BaseGeoEntity> pointMap) {
    LMap unwrap = map.unwrap(LMap.class);
    unwrap.flyTo(new com.haulmont.addon.maps.web.toolkit.ui.leaflet.shared.Point(
        pointMap.getPoint().getY(), pointMap.getPoint().getX()), 12D);
}

Обратите внимание, что метод flyTo принимает другой тип Point (не из JTS), поэтому координаты передаются в другом порядке. Вторым аргументом передается зум. Чтобы гарантировать, что на данном уровне зума уже не будет кластеров, можно для кластеризации определить параметр disableAtZoom (в нашем случае: 12).

Однако в этом же методе не получится сразу открыть popup, поскольку эти 2 операции наложатся друг на друга. Вместо этого надо дождаться завершения анимированного зума и после этого открыть popup. Это можно сделать, подписавшись на соответствующий эвент:

private PointMap zoomedPoint;

@Subscribe
public void onInit(InitEvent event) {
    map.addMoveEndListener(moveEndEvent -> {
        if (zoomedPoint != null) {
            VectorLayer<PointMap> pointMapVectorLayer = map.getLayer("pointVectorLayer");
            Map<?, GeoObjectWrapper<PointMap>> geoObjectWrappersMap = ((WebGeoMap)map).getGeoObjectWrappersMap(pointMapVectorLayer);
            GeoObjectWrapper<PointMap> geoObjectWrapper = geoObjectWrappersMap.get(zoomedPoint.getId());
            if (geoObjectWrapper != null) {
                geoObjectWrapper.openPopup();
            }
            zoomedPoint = null;
        }
    });
}

public void setSelectedGeoObject(PointMap<? extends BaseGeoEntity> pointMap) {
    ((VectorLayer<PointMap>) map.getLayer("pointVectorLayer")).setSelectedGeoObject(pointMap);

    zoomedPoint = pointMap;
    LMap unwrap = map.unwrap(LMap.class);
    unwrap.flyTo(new com.haulmont.addon.maps.web.toolkit.ui.leaflet.shared.Point(
        pointMap.getPoint().getY(), pointMap.getPoint().getX()), 12D);
}

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