Jump to content

Провайдеры тайлов в TfgMap с 1.15.3.0. OpenStreetMap


Viktor Akselrod

3,415 views

Вступление

Мы стараемся прислушиваться к потребностям наших клиентов. На этот раз мы добавили чрезвычайно важную возможность для всех пользователей карт — а именно возможность использования собственных изображений (тайлов) карт.

designer.png

Когда и кому это может понадобиться?

На первый взгляд стандартные поставщики карт имеют полноценный, законченный функционал и не требуют вмешательства со стороны программиста. Но, как это зачастую бывает в реальной жизни, есть нюансы. Что, если вам нужно единообразие карт на обоих платформах iOS и Android (напоминаем, кто каждая ОС имеет своего поставщика карт/тайлов)? Если вам нужен оффлайн доступ к картам? Если вы разрабатываете игру и вам нужно нарисовать необычный ландшафт? Так же вам может понадобиться выбор локального поставщика карт, который имеет лучшую детализацию для конкретной местности, в которой планируется использовать приложение. И это далеко неполный список, когда собственный провайдер тайлов может быть полезен.

Что такое тайлы? Модель тайлов

Тайлы — это подготовленные заранее изображения части карты из которых, как в пазле, строится полная карта. Каждый тайл имеет три основных характеристики: координата по оси X, координата  по оси Y, а так же зум, к которому принадлежит данный тайл. 
Чтобы понять, что означают эти характеристики в контексте карты, нужно разобраться с моделью тайлов. 
Как было сказано ранее, карта строится из прямоугольных кусков и, в первую очередь, загружаются только те тайлы, которые видимы на текущем экране, а не вся карта целиком. Данный подход позволяет как оптимизировать расходы трафика (т. к. чаще всего речь идет об онлайн поставщиках карт), так и ускорить загрузку видимой части карты в целом.
Карта имеет координатную сетку и зум. От уровня зума зависит разрешение координатной сетки. Чем выше зум, тем больше координатная сетка и тем выше детализация карты.
По этой ссылке можно наглядно увидеть зависимость разрешения карты от зума. 

Где взять тайлы?

Когда мы разобрались с вопросом зачем, надо понять кто и на каких условиях предоставляет тайлы. 
В первую очередь существует несколько крупных сервисов, которые специализируются на предоставлении тайлов. Как правило, поставщики имеют несколько планов — бесплатный с некоторыми ограничениями и платный доступ, когда количество запросов от вашего приложения превышает некий заранее оговоренный лимит. Краткий обзор основных поставщиков географических карт можно посмотреть по ссылке. Так же есть бесспорный лидер среди бесплатных поставщиков географических карт —  OpenStreetMap
И, конечно же, вы сами можете сделать свою собственную реализацию поставщика тайлов, если вам не подходит ни один из готовых вариантов.

Используем провайдеры тайлов в FGX Native

Библиотека FGX Native предусматривает несколько вариантов добавления альтернативных провайдеров тайлов в ваш проект.

Готовые провайдеры тайлов
На момент публикации статьи в поставке библиотеки есть только один готовый компонент-провайдер  TfgOSMMapTileProvider, который, как не сложно догадаться из названия, предоставляет доступ к тайлам сервиса OpenStreetMap. Не исключено, что со временем список готовых провайдеров будет пополняться новыми сервисами.
Использование: бросить на форму компонент TfgOSMMapTileProvider, в инспекторе объектов связать свойство TfgMap.TileProvider и компонент TfgOSMMapTileProvider.

Универсальные пользовательские провайдеры тайлов
Универсальные провайдеры дают большую гибкость по сравнению с готовыми провайдерами за счет того, что разработчик сам отвечает за предоставление тайлов. В библиотеке такие провайдеры  представлены компонентом TfgMapTileProvider. 
Использование: 
1) Прежде всего необходимо задать свойство TfgEventMapTileProvider.TileSize, которое отвечает за размер отдаваемых провайдером тайлов в пикселях.
Внимание: Смена размера тайла после задействования провайдера приведет к сбросу кэша тайлов карты и повторной загрузке карты.
2) Задать событие  TfgEventMapTileProvider.OnGetTile, в котором должен возвращаться графический тайл в виде интерфейса IFGXMapTile.
Внимание: Событие  OnGetTile вызывается асинхронно из вторичных (не UI потоков). Реализация события должна быть потокобезопасной.

Размер тайла всегда должен содержать актуальное, согласованное с реальным размером тайла значение. Если вам по какой-то причине нужно перенастроить провайдер — сначала отлинкуйте его от карты, настройте и потом прилинкуйте заново.
Типичный пример реализации события: 

function TFormMain.fgMapTileProvider1GetTile(Sender: TObject; const X, Y,
  Z: Integer; const AScale: Single): IFGXMapTile;
begin
  Result := TfgMapTileSource.CreateFromUrl(Format('https://stamen-tiles.a.ssl.fastly.net/watercolor/%d/%d/%d.png', [Z, X, Y]));
end;

В примере выше используется класс-хэлпер TfgDefaultMapTile , который реализует требуемый для результата события интерфейс IFGXMapTile.
Класс TfgDefaultMapTile содержит несколько конструкторов, каждый из которых отвечает за загрузку данных тайла тем или иным способом:

    constructor CreateFromBitmap(const ABitmap: TfgBitmap);
    constructor CreateFromFileName(const AFileName: string);
    constructor CreateFromStream(const AStream: TStream);
    constructor CreateFromUrl(const AUrl: string);

Собственная реализация провайдеров тайлов

Если же ни один из двух вышеперечисленных способов вам не подходит и нужен максимальный контроль над процессом — вам поможет собственная реализация провайдера тайлов и самих тайлов.
Реализация провайдеров строится на базе двух интерфейсов IFGXMapTileProvider и IFGXMapTile.
IFGXMapTile
За представление тайла в библиотеке FGX Native отвечает интерфейс  IFGXMapTile. Он имеет два свойства: сырые данные, содержащие изображение тайла в любом поддерживаемом графическом формате (обычно png) и размер данных в байтах.

  IFGXMapTile = interface
    ['{77F3C69D-6C83-4CAB-8A8C-6ED483B28275}']
    function GetData: Pointer;
    function GetSize: Integer;
    property Data: Pointer read GetData;
    property Size: Integer read GetSize;
  end;

IFGXMapTileProvider
Провайдер тайлов реализуется с помощью интерфейса IFGXMapTileProvider.
GetTileSize - возвращает общий для всех тайлов размер тайла в пикселях.
GetTile - возвращает тайл для указанных координат. Метод должен быть потокобезопасным.
AddObserver, RemoveObserver — подписка на уведомления/отписка от уведомлений. Реализация должна уведомлять всех заинтересованных наблюдателей об изменении размера тайла и разрушении провайдера. 

  IFGXMapTileProvider = interface
    ['{AE2174DA-7362-4566-A307-6164E31635F1}']
    function GetTileSize: TSize;
    function GetTile(const X, Y, Z: Integer; const AScale: Single): IFGXMapTile;
    procedure AddObserver(const AObserver: IFGXMapTileProviderObserver);
    procedure RemoveObserver(const AObserver: IFGXMapTileProviderObserver);
  end;

Использование: 
1) Реализовать интерфейс IFGXMapTileProvider.
2) По желанию реализовать интерфейс IFGXMapTile.
Данный тип провайдера идеально подойдет для реализации собственного кэша тайлов, оффлайн доступа к картам и тд, те там где нужна исключительная гибкость и полный контроль над процессом.

На этом знакомство с механизмом провайдеров тайлов подходит к концу. 

Спасибо за внимание.

  • Like 7
  • Thanks 2

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...