Биты и байты.

Биты и байты.

вторник, 24 июня 2014 г.

Рисуем простые фигуры в SQL

Давно интересовал вопрос, что можно оригинального нарисовать в SQL, кроме квадрата Малевича конечно...
С эти вопросом я отправился к поисковому серверу.
Вдохновившись найденными скриптами в интернете, я решил  исследовать эту тему дальше.
У SQL Server 2008 есть специальная вкладка для просмотра графических данных.




К сожалению редактора для рисования таких картинок я  так и не нашел
Но у далось выяснить много интересного

Типы geometry и geography
Для работы с пространственными типами данных еще в SQL Server 2008, появилось два типа geography и geometry.
Очень подробно работа с этими типами описана в книге Aitchison A. - Pro Spatial with SQL Server 2012
Тип данных geometry применяется к плоским фигурам  и имеет отношение к Евклидовой геометрии, где все объекты располагаются на плоской поверхности.  Для координат на плоскости используются координаты X,Y иногда и Z.

Тип данных geography используется для задания фигур, объектов и определения расстояния в условиях поверхности земли, т.е с учетом формы земли которая, как известно, является приплюснутым сфероидом.
Для координат на поверхности земли  используется долгота и широта и привязка к системе координат SRID (датуму , который представляет собой набор параметров смещения и поворота эллипсоида для лучшей аппроксимации земной поверхности. Также датум задаёт нулевой меридиан, от которого будет идти отсчёт долготы)
В настоящий момент практически все географические сервисы используют единую систему присвоения точке координат — WGS 84, он идет под кодом 4326

Ниже пример как перевести координаты из сферической системы в плоскую.
Математически она выражается следующим образом (для сферы):
x = R · λ;
y = R · ln(tg(π/4 + φ/2), где R — радиус сферы, λ — долгота в радианах, φ — широта в радианах.
На выходе получаем обычные декартовы координаты в метрах.

Скрипт ниже хорошо демонстрирует эти различия, в случае с типом география расстояния равно 635760 метров, что равняется 635 км в соответствии  с нашим идентификатором координат 4326  uint_of_measure = metre
Для геометрического типа получилось 472 км. Координаты UTM можно взять отсюда
Конвертировать напрямую из типа geography в тип geometry напрямую не получится, для этого нужно использовать формулы трансформации, которые описаны в книге.

--Тип география
DECLARE @MoscowGeog AS GEOGRAPHY= geography::Point(55.755787,37.617634, 4326);
DECLARE @SPetersburgGeog AS GEOGRAPHY= geography::Point(59.939037,30.315784, 4326);


--Тип геометрия, напрямую нельзя конвертировать SELECT CAST(@MoscowGeog AS geometry);
--DECLARE @MoscowGeom as geometry = geometry::STGeomFromWKB(@MoscowGeog.STAsBinary(), @MoscowGeog.STSrid);
--DECLARE @SPetersburgGeom as geometry = geometry::STGeomFromWKB(@SPetersburgGeog.STAsBinary(), @SPetersburgGeog.STSrid);

DECLARE @MoscowGeom as geometry = geometry::Point(6179494,413470,0);
DECLARE @SPetersburgGeom as geometry = geometry::Point(6647711,351165, 0);

SELECT @MoscowGeog.STDistance(@SPetersburgGeog) As 'Расстояние Москва-Санкт Петербург',  @MoscowGeog.ToString() WKT, @MoscowGeog.Lat "широта", @MoscowGeog.Long "долгота", @MoscowGeog.STSrid as STSrid
UNION ALL
SELECT @MoscowGeom.STDistance(@SPetersburgGeom) As 'Расстояние Москва-Санкт Петербург',  @MoscowGeom.ToString() ,  @MoscowGeom.STY, @MoscowGeom.STX , @MoscowGeom.STSrid

GO
--Идентификатор пространственной привязки (SRID) - это уникальный идентификатор, соответствующий привязке к  определенной системе координат
--список всех идентификаторов находится в таблице sys.spatial_reference_systems
SELECT   * FROM   sys.spatial_reference_systems t WHERE  t.spatial_reference_id = 4326


Список всех идентификаторов можно найти в таблице spatial_reference_systems

SQL сервер поддерживает  следующие способы задания геометрических объектов, самый простой понятный и наглядный это WKT его и будем дальше использовать .
WKT (WELL KNOWN TEXT, известный текстовый формат, применяемый для описания графических объектов), WKB является двоичным эквивалентом формата WKT и
GML (geography markup language, язык географической разметки)


В 2012 появились окружности и дуги  CIRCULARSTRING(0 4, 4 0, 8 4, 4 8, 0 4)

Чтобы задать элемент можно воспользоваться одной из четырех форм записи
--Precise Spatial method
SET @g = GEOMETRY::STPolyFromText('POLYGON( (0 0, 30 0, 30 30, 0 30, 0 0)) ',4326);
--Generic Spatial method
SET @g = GEOMETRY::STGeomFromText('POLYGON( (0 0, 30 0, 30 30, 0 30, 0 0)) ',4326);
--Short Format
SET @g = 'POLYGON( (0 0, 30 0, 30 30, 0 30, 0 0) )';
-- CLR form
SET @g = GEOMETRY::Parse('POLYGON( (0 0, 30 0, 30 30, 0 30, 0 0) )');

Для типа  Geometry кстати предусмотрено очень много полезных методов


По ссылке можно найти полное описание 

Вычисляет площадь
Возвращает представление  в формате WKB
Возвращает WKT-представление OGC
Возвращает все границы объекта
Расширяет объект на зону буфера
Возвращает геометрический центр
Содержит объект в себе geometry
Возвращает  выпуклую оболочку экземпляра geometry.
Возвращает 1 если объекты пересекаются
Возвращает кривую, указанную в экземпляре geometry
Вычитает из объекта другой объект geometry
Определяет точка, линия или полигон
Возвращает наименьшее расстояние между объектами
Возвращает конечную точку экземпляра geometry.
Возвращает прямоугольник вокруг объекта
проверяет совпадают ли объекты
Возвращает внешнюю границу объекта
Возвращает указанный номер элемента в коллекции
Возвращает имя типа OGC (точка, линия, полигон, кривая)
Возвращает внутреннюю границу объекта
Возвращает пересечение двух объектов
Возвращает 1 если объекты пересекаются
Возвращает 1, если начальная и конечная точки совпадают
Возвращает значение 1, если экземпляр geometry пуст
Возвращает 1, если экземпляр является кольцом
Возвращает 1, если экземпляр является простым
Проверяет является ли  экземпляр правильного формата
Возвращает общую длину элементов в экземпляре
Возвращает количество геометрических объектов
Возвращает суммарное количество точек в каждой из фигур в экземпляре.
Возвращает 1, если экземпляр перекрывает другой экземпляр
Возвращает конкретную точку в экземпляре geometry.
Возвращает произвольную точку, которая находится внутри экземпляра
Возвращает 1, если экземпляр связан с другим экземпляром
идентификатор пространственной ссылки экземпляра
Возвращает начальную точку экземпляра
Возвращает объект, представляющий все точки, принадлежащие одному из экземпляров, но не лежащие одновременно в обоих экземплярах.
Возвращает значение 1, если экземпляр пространственно соприкасается с другим экземпляром
Возвращает объект, представляющий объединение
Возвращает 1, если экземпляр находится полностью в другом экземпляре
Свойство координаты по оси X экземпляра Point
Свойство координаты по оси Y экземпляра Point

Новые возможности в SQL 2012
В 2012 появились окружности и дуги  CIRCULARSTRING(0 4, 4 0, 8 4, 4 8, 0 4), методы ShortestLineTo(), STIsValid(), IsValidDetailed(), MakeValid()
Поддержка полной модели земли а не полушария  (В 2008 можно отобразить данные в запросе если они находятся в одном полушарии)

-- Construct a new FullGlobe object (a WGS84 ellipsoid)
DECLARE @Earth geography = 'FULLGLOBE'
-- Calculate the area of the earth
SELECT PlanetArea = @Earth.STArea()

Подробно можно узнать здесь

Пример использования функций

DECLARE @p as GEOMETRY = 'POLYGON((50 0, 60 30, 80 20, 70 40, 100 50, 70 60, 80 80, 60 70,
                         50 100, 40 70, 20 80, 30 60, 0 50, 30 40, 20 20, 40 30, 50 0 ))'
SELECT @p as geom
UNION ALL
SELECT @p.BufferWithTolerance(-2,2,0)  /* 0, tolerance (2nd parm) is the absolute maximum variation in the
                                          ideal buffer distance for the returned linear approximation. */
UNION ALL
SELECT @p.BufferWithTolerance(-9,3,1) /* 1, tolerance is relative. Product of the tolerance parameter
                                            & the diameter of the bounding box */
UNION ALL
SELECT @p.STBuffer(-14)




Маляр красит стенку в сумашедшем доме . Подходит псих : -Ты крепко за кисточку держишься ? -Да - отвечает тот . -Тогда я лестницу забираю. 

About