Использование EnvelopeCenter для переменной Geography не возвращает правильное значение в SQL Server

У меня есть SQL-запрос, в котором я объявляю две переменные Geography, а затем пытаюсь найти центральную точку многоугольников после присвоения этим переменным значений.

Это мой код:

DECLARE @g1 GEOGRAPHY;
DECLARE @g2 GEOGRAPHY;

SET @g1 = geography::STGeomFromText('POLYGON((-90.06875038146973 35.512324341620996,-90.06767749786377 35.51504904492378,-90.06407260894775 35.51499664765537,-90.06381511688232 35.512219543493465,-90.06875038146973 35.512324341620996))',4326);
SET @g2 = geography::STGeomFromText('POLYGON ((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))',4326);

SELECT  @g1 AS 'G1' ,
        @g2 AS 'G2';

SELECT  'G1' AS 'Polygon' ,
        @g1.EnvelopeCenter().Lat AS 'Lat' ,
        @g1.EnvelopeCenter().Long AS 'Long'
UNION ALL
SELECT  'G2' AS 'Polygon' ,
        @g2.EnvelopeCenter().Lat AS 'Lat' ,
        @g2.EnvelopeCenter().Long AS 'Long'

Теперь для второго многоугольника он правильно возвращает значение широты/долготы центра как 47,6545001086162, -122,352999904254. Но для первого он возвращает значение 90, 0.

Почему я не получаю правильную центральную точку для первого многоугольника? Если по какой-то причине это невозможно, есть ли другой способ найти центральную точку для данной строки WKT?


person Raj    schedule 13.02.2017    source источник


Ответы (1)


Любая замкнутая линия на поверхности земного шара может описывать одно из двух различных конечных пространств. Чтобы узнать, какое пространство определяется, вам нужно определить, где находится «внутри» фигуры.

В этом случае G1 в настоящее время описывает большую часть земного шара за вычетом небольшого пространства около -90,066, 35,513.

Если вы хотите, чтобы он описывал небольшую часть земного шара, которая включает -90,066, 35,513, вам нужно изменить последовательность точек, которые вы используете для описания формы:

DECLARE @g1 GEOGRAPHY;
DECLARE @g2 GEOGRAPHY;

SET @g1 = geography::STGeomFromText('POLYGON((
                                              -90.06875038146973 35.512324341620996,
                                              -90.06381511688232 35.512219543493465,
                                              -90.06407260894775 35.51499664765537,
                                              -90.06767749786377 35.51504904492378,
                                              -90.06875038146973 35.512324341620996
                                              ))',4326);
SET @g2 = geography::STGeomFromText('POLYGON ((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))',4326);

SELECT  @g1 AS 'G1' ,
        @g2 AS 'G2';

SELECT  'G1' AS 'Polygon' ,
        @g1.EnvelopeCenter().Lat AS 'Lat' ,
        @g1.EnvelopeCenter().Long AS 'Long'
UNION ALL
SELECT  'G2' AS 'Polygon' ,
        @g2.EnvelopeCenter().Lat AS 'Lat' ,
        @g2.EnvelopeCenter().Long AS 'Long'

Результат (2):

Polygon Lat                    Long
------- ---------------------- ----------------------
G1      35.5136474138606       -90.0660789036838
G2      47.6545001086162       -122.352999904254

Это связано с тем, что именно последовательность точек, описывающая форму, используется для определения внутренней и внешней сторон формы — это называется «правилом левой руки».

person Damien_The_Unbeliever    schedule 13.02.2017
comment
Это идеально! 35,513, -90,066 - это то, что я ожидал увидеть. Но обычно я не контролирую последовательность вводимых точек, и в некоторых моих полигонах есть дыры. Итак, есть ли способ просто инвертировать пробел, если значение равно 90, 0? Потому что изменение последовательности точек вручную может привести к путанице, особенно если в многоугольнике есть дыры. - person Raj; 13.02.2017
comment
Если это невозможно, это нормально. Я обнаружил, что можно получить аналогичное значение, используя метод STCentroid(), который вместо этого возвращает центроид 'геометрической' переменной (мне просто нужно было приблизительное значение). И последовательность, кажется, не имеет значения в этом случае. Но мне просто интересно, возможно ли это. В любом случае большое спасибо за решение моей проблемы! - person Raj; 13.02.2017
comment
@Raj - вы могли бы добавить проверку работоспособности, используя STArea, и если она кажется довольно большой, вы могли бы использовать STDifference между текущей географией и FullGlobe? - person Damien_The_Unbeliever; 13.02.2017
comment
Я посмотрю, что. Спасибо Дэмиен! - person Raj; 13.02.2017
comment
@Raj: Чтобы ответить на ваш вопрос об инвертировании пространства, есть метод ReorientObject(), доступный для экземпляров geography, чтобы сделать именно это! - person Ben Thul; 13.02.2017
comment
Кроме того, моя проверка вменяемости обычно @g.EnvelopeAngle > 90. - person Ben Thul; 13.02.2017