Рисование На Плитках Электронной Карты В Mssql

Хочу рассказать читателям хабра-сообщества, как пользоваться библиотекой CLR. Microsoft.SqlServer.Types Вы можете создавать тайлы для электронной карты.

В статье речь пойдет о формировании списка картографических тайлов для их дальнейшей отрисовки.

Будет описан алгоритм генерации тайлов на основе геометрии объекта, хранящейся в базе данных MS SQL 2008. Весь процесс рендеринга будет рассмотрен шаг за шагом на примере в конце статьи.



Рисование на плитках электронной карты в MSSQL



Содержание




Проблема Исходные данные Решение Хранение плитки ?Этапы подготовки плитки Используемые функции Пример с ломаной линией Проверка перекрестка Таблицы для хранения изображений тайлов Размещение значка на плитке Объединение плиток Рисование геометрии на плитке Заключение

Проблема




Когда браузер отображает большой объем геоданных в векторной графике (с использованием SVG или CANVAS), иногда приходится ждать не только загрузки данных на клиентский компьютер, но и завершения процесса рендеринга, что может занять некоторое время.

много времени.

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

Исходные данные:




Набор геометрических объектов хранится в таблице базы данных Microsoft SQL 2008. Координаты узлов — широта и долгота (EPSG:4326).

Поле геоданных имеет тип ГЕОМЕТРИЯ .

Объекты должны отображаться на карте в виде значков, для геометрии Точка .

В виде ломаной линии определенной толщины для геометрии.

Полилиния .

Геометрия многоугольника должна выглядеть как один или несколько заполненных многоугольников с контуром.

Плитки должны соответствовать проекции Веб-Меркатор

Решение:




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

Для этого необходимо для каждого масштаба подготовить набор картографических плиток с изображениями объектов.

Для формирования тайлов воспользуемся проекцией Google Веб-Меркатор , то есть преобразование широты и долготы в пиксели карты будет выполняться с помощью кода Google, который использует формулы, описывающие проекцию Меркатор : Подробнее о прогнозах можно прочитать Здесь .

Начиная с Sql Server 2008 поддерживается тип данных для работы с пространственными данными.

ГЕОМЕТРИЯ И ГЕОГРАФИЯ .

Существующие картографические сервисы Яндекса, Google или OpenStreetMap предоставляют картографию в виде изображений PNG фиксированного размера, обычно 256x256 пикселей.

Хотя сейчас есть сервисы, где тайлы генерируются с помощью таких технологий, как SVG или CANVAS. Мы будем рассматривать растровые тайлы в формате PNG (картинка сетевая графика).

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



Хранение плитки




Для каждого масштаба хранится определенный набор тайлов.

Для шкалы уровня 0 – 1 плитка:

Рисование на плитках электронной карты в MSSQL

Для шкалы 1-го уровня предусмотрены четыре плитки 2*2:

Рисование на плитках электронной карты в MSSQL

для масштаба n хранится 2n * 2n тайлов.

Количество плиток увеличивается экспоненциально с увеличением номера шкалы.

Тайлы хранятся в файловой системе веб-сервера и отправляются на клиентскую машину посредством http-запроса, например: сомерл/слой {Z}/{X}/{Y}.

png где Z,X,Y — масштаб, X — позиция плитки, Y — позиция плитки.

Например, по следующему адресу доступна плитка с изображением Троицкого моста в Санкт-Петербурге: b.tile.openstreetmap.org/15/19144/9524.png В этом URL: 15 – номер шкалы; 19144 – позиция плитки X; 9524 – Положение плитки по оси Y. Естественно, формат URL-адреса запроса различается в разных системах.

Вместо номеров плиток и масштаба вы можете использовать КВАД-ключ .

Файлы тайлов могут отправляться клиенту сервером напрямую из файловой системы или с помощью http-обработчиков.

Мы рассмотрим вариант с X, Y, Z.

?Этапы подготовки плитки




  • Генерация списка тайлов на основе геометрии каждого объекта;
  • Генерация тайлов для каждого объекта;
  • Объединение плиток для получения уникального набора;
  • Сохранение в файловую систему.



Используемые функции




Для реализации задачи вам понадобится функция генерации геометрии тайла на основе позиций X, Y тайла и номера масштаба.

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

Формирование такой геометрии может быть реализовано в функциях SQL или в функциях SQL CLR. Разница во времени выполнения функции SQL CLR и обычной функции SQL не заметна.

Код SQL CLR для этой функции реализован в классе Coords2PixelConversion в прилагаемом исходном коде.

Следующая геометрия представляет собой контур этого тайла, то есть проходит вдоль его границ.

Координаты вершин здесь — долгота и широта.

Геометрия границы плитки

  
  
  
   

'POLYGON ((30.322265625 59.955010262062061, 30.322265625 59.949509172252277, 30.333251953125 59.949509172252277, 30.333251953125 59.955010262062061, 30.322265625 59.955010262062061))'

Код скалярной функции SQL tile.GetTileBounds()

tile.GetTileBounds(@level int, @x int, @y int) CREATE FUNCTION [tile].

[GetTileBounds] (@level int, @x int, @y int) RETURNS geometry AS BEGIN DECLARE @res GEOMETRY = NULL IF @level IS NOT NULL AND @x IS NOT NULL AND @y IS NOT NULL BEGIN DECLARE @n1 FLOAT = PI() - 2.0 * PI() * @y / POWER(2.0, @level); DECLARE @n2 FLOAT = PI() - 2.0 * PI() * (@y + 1) / POWER(2.0, @level); DECLARE @top FLOAT = (180.0 / PI() * ATAN(0.5 * (EXP(@n1) - EXP(-@n1)))); DECLARE @bottom FLOAT = (180.0 / PI() * ATAN(0.5 * (EXP(@n2) - EXP(-@n2)))); DECLARE @tileWidth FLOAT = 360 / CONVERT(float, POWER(2, @level)) DECLARE @left FLOAT = @tileWidth * @x - 180, @right FLOAT = @tileWidth * (@x + 1) - 180 SET @res = geometry::STPolyFromText('POLYGON ((' + LTRIM(STR(@left, 25, 16)) + ' ' + LTRIM(STR(@top, 25, 16)) + ', ' + LTRIM(STR(@left, 25, 16)) + ' ' + LTRIM(STR(@bottom, 25, 16)) + ', ' + LTRIM(STR(@right, 25, 16)) + ' ' + LTRIM(STR(@bottom, 25, 16)) + ', ' + LTRIM(STR(@right, 25, 16)) + ' ' + LTRIM(STR(@top, 25, 16)) + ', ' + LTRIM(STR(@left, 25, 16)) + ' ' + LTRIM(STR(@top, 25, 16)) + '))', 0) END RETURN @res END

Как использовать эту функцию, будет описано далее в этой статье.

Давайте рассмотрим методы генерации списка тайлов.

Для разной геометрии вы можете выбрать разные подходы к созданию списка тайлов.

Метод 1: Воспользуемся этим обстоятельством: Если в одном масштабе объект не пересекается с плиткой, то в масштабе с большим номером 4 плитки, перекрывающие проверяемую плитку, также не пересекаются с объектом.

То есть при переходе к следующему масштабу мы проверяем тайл только в том случае, если тайл предыдущего масштаба пересекается с геометрией объекта.

Это исключает ненужные проверки, которые выполняются в методе 2. Метод 2: На самом деле этот метод является наихудшим сценарием.

Для каждого масштаба для каждого объекта определите подмножество плиток с помощью функции ГЕОМЕТРИЯ::STEnvelope() и проверяем пересечение тайла из этого подмножества с объектом.

Этот метод менее эффективен, особенно для объектов большой площади или длины, поскольку проверяется большее количество тайлов.

Способ 3: Для каждого объекта сгенерируйте геометрию тайловой сетки и в месте пересечения сетки с геометрией объекта получите набор точек.

Для каждой полученной точки определите две плитки и добавьте их в окончательный список плиток.

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

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

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

Опишем первый способ более подробно.

Для геометрий объекта с площадью набор тайлов для проверки пересечения с объектом может быть ограничен крайними тайлами прямоугольной области (bbox), перекрывающими объект. По геометрии объекта (кроме типа геометрии ТОЧКА ) прямоугольник формируется функцией CLR MSSQL ГЕОМЕТРИЯ::STEnvelope().

Для объектов с геометрией ТОЧКА Граница bbox представляет собой прямоугольную область, перекрывающую значок объекта на карте.

Функция GetImageBound , возвращающий геометрию перекрывающейся иконки, реализованную в классе GoogleПроекция .

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

Координаты угловых точек прямоугольной области выражаются в широте и долготе.

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

Для этого нам нужна функция для преобразования географических координат в номер тайла в соответствующем масштабе.

Чтобы получить положение плитки по X и Y по долготе и широте, мы можем использовать как функции SQL CLR, которые будут приведены ниже, так и функции SQL, приведенные ниже:

tile.GetXTilePos((@Longitude FLOAT, @Zoom INT) tile.GetYTilePos((@Latitude FLOAT, @Zoom INT)

После определения положения угловых плиток все плитки, расположенные в прямоугольной области между найденными угловыми плитками, проверяются на пересечение с геометрией объекта в функции tile.fn_FetchGeometryTilesZoomDepth() .

Функция SQL для получения положения плитки X для долготы и номера масштаба

CREATE FUNCTION tile.GetXTilePos(@Longitude FLOAT, @Zoom INT) RETURNS INT AS BEGIN

Теги: #ГИС #CLR #c#.

net #mssql 2008 #Microsoft SQL Server #C++ #Геоинформационные сервисы #Визуализация данных

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.