ГИС находит точки (длинные латы), которые содержатся в полигоне, выраженном в виде набора длинных лат
-
16-09-2019 - |
Вопрос
Я пытаюсь найти все элементы данных, которые имеют длину / lats, которые содержатся в полигоне, состоящем из массива длинных lats, может быть много точек.Я знаю, что вы можете делать подобные вещи с новыми геопространственными типами данных в SQL 2008, но я использую SQL 2005 и C #.Было бы лучше всего сделать это в конце базы данных или на C #.
Спасибо.
Решение
У меня есть некоторый код, написанный для SQL2000, чтобы сделать это.Он использует метод "угла" для определения, лежит ли точка внутри многоугольника.
Во-первых, определяемая пользователем функция getAngle:
ALTER Function [dbo].[GetAngle](
@Ax Decimal(8,5),
@Ay Decimal(8,5),
@Bx Decimal(8,5),
@By Decimal(8,5),
@Cx Decimal(8,5),
@Cy Decimal(8,5))
Возвращает значение Float Как Begin
Declare @dot_product Float
Declare @cross_product Float
Declare @BAx Decimal(8,5)
Declare @BAy Decimal(8,5)
Declare @BCx Decimal(8,5)
Declare @BCy Decimal(8,5)
--' Get the vectors' coordinates.
Set @BAx = Sign(@Ax - @Bx) * dbo.CalculateDistance(@Ax, @Ay, @Bx, @Ay)
Set @BAy = Sign(@Ay - @By) * dbo.CalculateDistance(@Ax, @Ay, @Ax, @By)
Set @BCx = Sign(@Cx - @Bx) * dbo.CalculateDistance(@Cx, @Cy, @Bx, @Cy)
Set @BCy = Sign(@Cy - @By) * dbo.CalculateDistance(@Cx, @Cy, @Cx, @By)
--' Calculate the dot product.
Set @dot_product = @BAx * @BCx + @BAy * @BCy
--' Calculate the Z coordinate of the cross product.
Set @cross_product = @BAx * @BCy - @BAy * @BCx
--' Calculate the angle.
return ATn2(@cross_product, @dot_product)
Конец
Далее я предполагаю, что существует табличная переменная пар Широта / Долгота и порядковый номер (указывающий порядок, в котором пары ШИРОТА / длина определяют многоугольник).Важно, чтобы первый пункт в этой таблице совпадал с последним пунктом в таблице.
Кроме того, у меня есть несколько переменных для минимальной и максимальной широты и долготы.Это эффективно создает ограничивающую рамку, так что я могу быстро удалять точки, НЕ входящие в прямоугольную область, ограничивающую многоугольник.
Select Address.AddressId
From @Temp As A
Inner Join @Temp As B
On A.SequenceNumber = B.SequenceNumber - 1
Inner Join Address
On Address.XCoord Between @MinLongitude And @MaxLongitude
And Address.YCoord Between @MinLatitude And @MaxLatitude
Group By Address.AddressId
Having Abs(Sum(dbo.GetAngle(A.Longitude, A.Latitude, Address.XCoord, Address.YCoord, B.Longitude, B.Latitude))) > 3.14
Другие советы
Это звучит как что-то, что вызывает головную боль, если делать это на T-SQL (хотя это более или менее все?).Конечно, это зависит от сложности полигонов и способа расположения элементов данных, но в целом самым простым и умеренно эффективным подходом может быть выполнение некоторых первоначальных вычислений на C#, что очень грубо ограничивает элементы данных.Итак, что-то вроде следующего.
- Рассчитайте приблизительные границы многоугольника на C#.
- Получите все, что находится внутри этих границ, с SQL-сервера.
- Выполните окончательную точную фильтрацию на C#.
Производительность, конечно, зависит от того, насколько хорошо вы сможете рассчитать начальные границы.Я бы сначала начал с простого ограничивающего прямоугольника и посмотрел, достаточна ли производительность.