Эффективный способ загрузки большого количества точек (геометрий) на карту

    Привет, Хабр.


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


    Quick Dive


    С точки зрения большинства современных картографических решений можно выделить несколько базовых подходов к отрисовке карты:


    • растровый (статичные файлы — картинки с тайлами, хранящиеся на CDN и имеющие свой TTL)
    • векторный

    Тут нужно сделать ремарку, тайл, для тех кто не вкурсе, это специальная блочная координатная сетка (параллельно тайлами называются и статичные изображения), которая характеризуется тремя координатами (z — зум, x, y), на каждом уровне количество тайлов $2^{(2 \times zoom)}$


    Наиболее интересным на сегодняшний день является векторный формат.


    Почему? Собственно, нужно начать с проблем, связанных с растровым форматом:


    • Дискретные уровни зума (от 0 до 20 в большинстве случаев)
    • Жёсткая привязка стилистики и данных на тайловых слоях
    • Классические недостатки растра

    Какие перспективы предлагает векторный формат? Собственно, их несколько:


    • Зум не связан чётко с тайлами на определённом слое, а может меняться с любой точностью и плавностью
    • Поскольку зачастую именно клиент (не рассматривая вариант промежуточного рендера) рендерит карту, то именно он определяет какие данные и в каком стиле он хочет отрисовывать
    • Отличное качество в независимости от разрешения и т.д., что в общем-то классическое преимущество вектора над растром

    Собственно всё с векторным форматом хорошо, но есть и свои недостатки. Как минимум, векторный формат сложнее кэшировать, это не так очевидно, как в большинстве случаев с растровым форматом, где достаточно предгенерированные тайлы сложить на CDN, настроить TTL и перегенерацию и больше не думать об этом.


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


    Решение


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


    1. Загрузка целиком GeoJSON и рендер его (большинство отваливаются на этом варианте :)). Собственно преимущество, в том что практически все популярные библиотеки Google Карты, Yandex Карты, Mapbox, Leaflet и т.д., его так или иначе поддерживают. Однако, далеко не все делают это эффективно, например, по запросу в гугл по поводу эффективного решения для загрузки большого числа точек в Mapbox первой ссылкой будет их решение — supercluster, который по факту является серверной утилитой, которая загружает, подготавливает GeoJSON данные и возвращает их клиенту.


    2. Загрузка только находящегося в viewport. Идея довольно простая, мы загружаем только то что находится в viewport (* в некоторых случаях лениво подгружаются и близлежащие тайлы). Реализация такого есть в коробке например в Yandex Картах — LoadingObjectManager, в том числе он может делать и кластеризацию на клиенте. У них есть и RemoteObjectManager, который уже ожидает кластеризованные данные от сервера.


    3. Предгенерация статичных тайлов и загрузка их. Тоже имеет место быть, особенно в случае с высоконагруженными сервисами, но не особо интересно. Чаще всего генерируются тайлы с помощью инструмента, как например Mapnik и заливаются на CDN, либо используется сторонняя утилита/библиотека, которая делает всю эту работу самостоятельно.


    4. Mapbox Vector Tiles, собственно один из векторных форматов для карт, который описывает различные геометрии, их стилистику и т.д… Идея при использовании такого метода заключается в формировании своего MVT эндпоинта, который собственно может:
      • Возвращать геометрии
      • Кластеризовать точки
      • Упрощать геометрии на малых уровнях зума
      • Другое

    Данный формат отлично поддерживается решениями от Mapbox, так же есть библиотеки для Leaflet.


    С точки зрения хранилища для ГИС данных, которое бы к тому же давало возможность эффективно проводить операции над ними можно выбрать PostGIS, который к слову даёт все необходимые операции для описанного выше, в том числе и генерацию MVT (Mapbox Vector Tiles):


    • Включение геометрии в тайл (прямоугольник) с помощью оператора @
    • Генерация MVT — ST_AsMVT, ST_AsMVTGeom

    Спасибо за внимание, надеюсь на конструктивный фидбэк, если будет интересно могу рассказать ещё о некоторых моментах работы с картами!


    Примеры описанного выше доступно в моём GitHub

    Поделиться публикацией
    Комментарии 5
      +1
      Так какой способ-то? :D
        0
        Зависит от потребностей, но в целом это 2 или 4 — ый. Я сам сейчас в разрабатываемом проекте остановился на втором, поскольку там уже были Яндекс Карты, в целом я сторонник векторного решения, как более состоятельного, но нужно потратить немного больше сил на бэкэнд, в идеале вообще была бы около микросервисная архитектура и использование готового решение на JS (да, на нём действительно очень много всего).

        Вообще, для своей книги я готовлю это всё очень подробно и даю некоторые хинты по поводу организации процессов, если будет лишнее время упрощу, обрежу и выложу на хабр и/или в свой блог.
        0
        Выглядит как небольшая заметка для себя. Обзор кратенько и самопиар небольшой. Извините, но это минус.
        PS: продолжение хоть будет?
          +1

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


          По поводу самопиара "небольшого", дважды внимательно просмотрел статью и не увидел ничего такого. А если Вы говорите про ссылку в репозитории, то как раз за ней и находится небольшой разбор кода, который я думал уместить в следующем посте на хабр.

            0
            Подписался, жду продолжения.

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

        Самое читаемое