Хочу рассказать читателям хабра-сообщества, как пользоваться библиотекой CLR. Microsoft.SqlServer.Types Вы можете создавать тайлы для электронной карты.
В статье речь пойдет о формировании списка картографических тайлов для их дальнейшей отрисовки.
Будет описан алгоритм генерации тайлов на основе геометрии объекта, хранящейся в базе данных MS SQL 2008. Весь процесс рендеринга будет рассмотрен шаг за шагом на примере в конце статьи.
Содержание
Проблема Исходные данные Решение Хранение плитки ?Этапы подготовки плитки Используемые функции Пример с ломаной линией Проверка перекрестка Таблицы для хранения изображений тайлов Размещение значка на плитке Объединение плиток Рисование геометрии на плитке Заключение
Проблема
Когда браузер отображает большой объем геоданных в векторной графике (с использованием SVG или CANVAS), иногда приходится ждать не только загрузки данных на клиентский компьютер, но и завершения процесса рендеринга, что может занять некоторое время.
много времени.
При отображении большого количества значков на карте в браузере можно использовать кластеризацию, но для сложных геометрических объектов нужно использовать другой подход.
Исходные данные:
Набор геометрических объектов хранится в таблице базы данных Microsoft SQL 2008. Координаты узлов — широта и долгота (EPSG:4326).
Поле геоданных имеет тип ГЕОМЕТРИЯ .
Объекты должны отображаться на карте в виде значков, для геометрии Точка .
В виде ломаной линии определенной толщины для геометрии.
Полилиния .
Геометрия многоугольника должна выглядеть как один или несколько заполненных многоугольников с контуром.
Плитки должны соответствовать проекции Веб-Меркатор
Решение:
Вместо векторной графики мы будем отображать объекты на карте в виде растрового слоя, то есть теми же изображениями (тайлами), что и сама карта.
Для этого необходимо для каждого масштаба подготовить набор картографических плиток с изображениями объектов.
Для формирования тайлов воспользуемся проекцией Google Веб-Меркатор , то есть преобразование широты и долготы в пиксели карты будет выполняться с помощью кода Google, который использует формулы, описывающие проекцию Меркатор : Подробнее о прогнозах можно прочитать Здесь .
Начиная с Sql Server 2008 поддерживается тип данных для работы с пространственными данными.
ГЕОМЕТРИЯ И ГЕОГРАФИЯ .
Существующие картографические сервисы Яндекса, Google или OpenStreetMap предоставляют картографию в виде изображений PNG фиксированного размера, обычно 256x256 пикселей.
Хотя сейчас есть сервисы, где тайлы генерируются с помощью таких технологий, как SVG или CANVAS. Мы будем рассматривать растровые тайлы в формате PNG (картинка сетевая графика).
Формат PNG поддерживает прозрачность (обозначается в альфа-канале), благодаря этому можно накладывать тайлы друг на друга без абсолютного перекрытия при отображении нескольких слоев.
Хранение плитки
Для каждого масштаба хранится определенный набор тайлов.
Для шкалы уровня 0 – 1 плитка:
Для шкалы 1-го уровня предусмотрены четыре плитки 2*2:
для масштаба 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 в прилагаемом исходном коде.
Следующая геометрия представляет собой контур этого тайла, то есть проходит вдоль его границ.
Координаты вершин здесь — долгота и широта.
Геометрия границы плитки
Код скалярной функции SQL tile.GetTileBounds()'POLYGON ((30.322265625 59.955010262062061, 30.322265625 59.949509172252277, 30.333251953125 59.949509172252277, 30.333251953125 59.955010262062061, 30.322265625 59.955010262062061))'
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++ #Геоинформационные сервисы #Визуализация данных
-
Использование Карты «Тройка» Как Полиса Омс
19 Oct, 24 -
Учимся Писать: Быть Или Не Быть Собой
19 Oct, 24