Зміна "хендлінгу" багатокутника для SQL 2008 (порядок зворотних вершин багатокутника)


11

У мене є кілька сотень форм ( polygonив multipolygon), кожна з яких складається з десятків тисяч точок, які я намагаюся потрапити в SQL 2008.

На жаль, фігури, які я намагався імпортувати, є "правою рукою" (периметр кожної з них намальований за годинниковою стрілкою навколо точок, які вона містить). Принаймні для geographyтипів SQL-сервер припускає фігури зліва (проти годинникової стрілки навколо інтер'єру) . Це означає, що SQL передбачає, що я намагаюся вибрати всю землю, за винятком форми. Деякі люди описують це як форми "всередину".

З MSDN , який розчаровує не сказати, яку орієнтацію кільця потрібно використовувати:

Якщо ми використовуємо geographyтип даних для зберігання просторового екземпляра, ми повинні вказати орієнтацію кільця і ​​точно описати розташування екземпляра.

Якщо ви використовуєте неправильну орієнтацію кільця в SQL 2008, воно виходить із ладу з наступною помилкою (міна акценту):

Помилка .NET Framework сталася під час виконання визначеної користувачем рутини або сукупної "географії": Microsoft.SqlServer.Types.GLArgumentException: 24205: Вказаний вхід не являє собою дійсний екземпляр географії, оскільки він перевищує єдину півсферу. Кожен екземпляр географії повинен вміщуватися всередині однієї півкулі. Поширеною причиною цієї помилки є те, що багатокутник має неправильну орієнтацію кільця.

Імпорт фігур як geometryзамість geographyпрацює чудово, але я хотів би скористатися, geographyякщо зможу.

У SQL 2012 видається досить банальним виправити цю проблему, але я прив’язаний до 2008 року.

Як перетворити фігури?


1
+1 чудове запитання ... чи є у вас посилання, де написано, що сервер Sql приймає ліві форми?
Кірк Куйкендалл

@Kirk Спасибі У мене виникають проблеми з пошуку офіційної документації, але я можу зв’язатись з MSDN, де йдеться про "орієнтацію на дзвінок" (хоча в ній не вказано, який спосіб використовувати). Я також вкладу помилку, яку отримує, коли вона виходить з ладу.
Майкл - Де Клей Ширкий

Відповіді:


14

Блог Spatial Ed мав стисле рішення. Ось кілька SQL, що демонструють перетворення:

DECLARE @geom GEOMETRY = 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))';
DECLARE @geog GEOGRAPHY = @geom.MakeValid().STUnion(@geom.STStartPoint()).STAsText()

І уривок з поста Еда:

Запорукою такої поведінки є STUnion()метод. Оскільки це метод на основі OGC, який працює над усією геометрією для даної функції, він змушує багатокутники в орієнтації, необхідній для методу - що, як буває, є тим, що використовується для Geographyтипу [...]. Цей ілюстрований метод є досить ефективним, зберігаючи накладні невеликі [...].


2
На SQL Server 2008 r2 мені довелося поставити .MakeValid () на внутрішній стороні STUnion (), а також, щоб це працювало: .STUnion (@ geom.MakeValid (). STStartPoint ())
Кріс Сміт,

@Smitty Це має сенс у випадках, коли SQL інакше не може визначити початкову точку. Можливо, якщо форма подвоюється назад над собою чи іншими дивними обставинами?
Майкл - Де Clay Shirky

Так, в моїх обставинах форма є хиткою і перекриває себе.
Кріс Сміт

0

У> = SQL Server 2012 метод ReorientObject () повинен досягти цього. Для <SQL Server 2012 нижче наведено альтернативний метод.

Для існуючої географії SQL @g, кодом нижче буде витягнути точки і знову створити багатокутник з точками (вершинами) у зворотному порядку:
(ПРИМІТКА 1: працює для простих багатокутників, а не для багатополігонів або полігонів з кільцями / центроїдами)
(ПРИМІТКА 2: використання системи координат SRID 4326 (WGS 84)

--For existing geography @g
DECLARE @GeometryText varchar(max), @ReversedPolygon geography
DECLARE @GeometryType varchar(20) = 'POLYGON', @Count int
SET @Count = @g.STNumPoints()
WHILE @Count > 0
BEGIN
    SET @GeometryText = @GeometryText + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Long)) + ' ' + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Lat))
    SET @Count = @Count - 1
    IF @Count > 0 SET @GeometryText = @GeometryText + ','
END
SET @GeometryText = @GeometryType +'((' + @GeometryText + '))'
SET @ReversedPolygon = geography::STGeomFromText(@GeometryText, 4326); 

0

Схоже, я можу використовувати якийсь нечесний гібрид SQL та C # від просторових інструментів SQL Server , як це запропоновано у переповненні стека .

Примітка. На момент опублікування цієї відповіді там було не так багато інформації. Не намагайтесь використовувати цей метод, якщо вам вже не потрібні просторові інструменти SQL Server для чогось іншого. Натомість спробуйте один з інших відповідей тут або на Стек переповнення .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.