2012-03-16 2 views
6

В моем SQL Server (2008 R2) на Azure, есть таблица, содержащая множество географических Points (широта/долгота):Создание географии многоугольник точек в T-SQL

CREATE TABLE MyPoints 
(
    Region uniqueidentifier NOT NULL, 
    Number int NOT NULL, 
    Position geography NOT NULL, 
    CONSTRAINT PK_MyPoints PRIMARY KEY(Region, Number) 
) 

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

Есть ли собственный и быстрый способ построения многоугольника из заданных точек в T-SQL? The solutions I found используют методы STGeomFromText/STGeomFomWKB для создания многоугольника, который кажется мне очень громоздким и медленным.

Что-то вроде:

SET @POLY = geometry::STPolyFromPoints(SELECT Position FROM MyPoints) 

ответ

3

Насколько я знаю, нет родной функции, которая принимает таблицу в качестве параметра и преобразует его в многоугольник.

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

UDF to Concatenate Column to CSV String

MSDN - STPolyFromText

+1

Мы используем функцию, которая объединяет точки в их двоичном представлении и вызывать 'STGeomFromWKB' в этой строке. Это достаточно быстро для нашей цели, но это все еще некрасиво. – Gene

+0

Еще одно предложение - написать свою собственную пользовательскую функцию .NET CLR, которая принимает параметр таблицы (столбец фактических точек геоданных) и возвращает геометрию. Я еще не работал с ним, но SqlGeometryBuilder выглядит многообещающим: http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometrybuilder.aspx –

+0

AFAIK нет поддержки функций CLR на SQL Azure. Я тоже думал об этой возможности. – Gene

3

Предполагая, что у нас есть таблица полной упорядоченных долгот и лат в этой таблице:

CREATE TABLE [dbo].[LongAndLats](
    [Longitude] [decimal](9, 6) NULL, 
    [Latitude] [decimal](9, 6) NULL, 
    [SortOrder] [int] NULL 
    ) 

Это будет переоборудовать эти точки в многоугольник:

DECLARE @BuildString NVARCHAR(MAX) 
SELECT @BuildString = COALESCE(@BuildString + ',', '') + CAST([Longitude] AS NVARCHAR(50)) + ' ' + CAST([Latitude] AS NVARCHAR(50)) 
FROM dbo.LongAndLats 
ORDER BY SortOrder 

SET @BuildString = 'POLYGON((' + @BuildString + '))'; 
DECLARE @PolygonFromPoints geography = geography::STPolyFromText(@BuildString, 4326); 
SELECT @PolygonFromPoints 

Некоторые примечания:

  • Полигон должен быть закрыт. то есть. первая и последняя точка должны быть одинаковыми.
  • Должно иметь мин. 4 очка.
  • Порядок пунктов очень важен. Он должен следовать «правилу левой руки/ноги» (области, лежащие на левой стороне линии, проведенной между точками, считаются внутри полигона)
+0

Мне было бы интересно узнать, как сделать фактическую сортировку, так как ваше выше решение отлично. Я повесил трубку, чтобы отсортировать точки в «правиле левой руки/ноги». Я заканчиваю полигон, который перекрывается сам по себе, потому что мой лат/длинный порядок не прав. –

+0

пример: 'DECLARE @geom GEOMETRY = ' POLYGON (( -116).77953600883484 \t +33,103710174560547 , -117,03299999237061 \t 32,547900199890137 , -117,11846709251404 \t 33,469111442565918 , -117,38499999046326 \t 33,202700138092041 , -117,38700008392334 \t 33,206999778747559 , -117,39700007438660 \t 33,209300041198730 , -116,77953600883484 \t 33,103710174560547 ))» ЗАЯВЛЯЮ @geog ГЕОГРАФИЯ = @ geom.MakeValid(). STUnion (@ geom.MakeValid(). STStartPoint()). STAsText() select @ geog' –

+0

@Smitty, заказ должен быть известен перед вставкой в ​​таблицу '[dbo]. [LongAndLats]'. Я не знаю, как определить надежный непересекающийся порядок сортировки, если точки не упорядочены, я не думаю, что это возможно, потому что не существует n возможных порядков сортировки. – g2server