Географическая точка внутри многоугольника показывает неверные результаты

В моей базе данных есть таблица, содержащая набор полигонов и их атрибутов, а также другая таблица, содержащая набор точек, координаты которых находятся внутри границ этих многоугольников. Я подключил QGIS к своей базе данных, чтобы убедиться, что они расположены именно там, где я ожидал, а затем выполнил запрос, чтобы определить идентификатор Polygon_id, внутри которого находится каждая точка. Это привело к очень неожиданным результатам, поэтому я провел еще несколько тестов и доработок, но все еще ничего не понял.

Я выделил одну точку и многоугольник, в который она попадает, и вот как она отображается в QGIS, используя тот же CRS (4326), подключаясь к моей базе данных:

Однако когда я использую STContains или STIntersect, я получаю отрицательный результат.

Когда я запускаю следующий тест, результаты показывают, что точка не существует в многоугольнике:

declare @p geography   
declare @l geography      

set @p = geography::STMPolyFromText('MULTIPOLYGON (((-2.01723932071019 57.1301507994778, -2.05959736945859 57.1308481812907, -2.06094305103518 57.1309872145762, -2.06442332315307 57.1311592624651, -2.06738702460041 57.131260961538, -2.06834761818132 57.1312257047487, -2.07352085461956 57.1308074773011, -2.08662715692557 57.1284264355531, -2.08835456332902 57.1282051063708, -2.0891720244275 57.1281861098907, -2.09070679418533 57.1283121889021, -2.09310621355588 57.1286955641499, -2.09502104689506 57.1293780321133, -2.09674004600622 57.1304564574772, -2.09753934746642 57.1297443781977, -2.09875197034386 57.1291864729083, -2.10340075289855 57.1282116756316, -2.10590378101433 57.1284283727703, -2.10916734028092 57.129042168269, -2.1099366825462 57.1291282326644, -2.11138826300974 57.1291886324809, -2.11294222137845 57.1287904597294, -2.11432776064015 57.1284126116958, -2.11590135588206 57.1272468512517, -2.11783267950974 57.1257414916239, -2.11972005111187 57.1230896037971, -2.12220448182387 57.1236735070728, -2.12237561434298 57.1239917795713, -2.12132109065263 57.1242488139312, -2.1173707565196 57.129607293332, -2.11658292484552 57.1328230202163, -2.11554089667428 57.1347555681128, -2.11504663847733 57.1359238965379, -2.11507076780594 57.1361851484318, -2.11527759405925 57.1364937439207, -2.11485673955606 57.1366369506911, -2.11452832733778 57.1372965941222, -2.1140394284489 57.1392757110769, -2.11377688986274 57.1399955310532, -2.11295601438074 57.1418667234446, -2.11208273346248 57.1427865720397, -2.10218925747153 57.1456872698938, -2.10042721504413 57.1441390669773, -2.09826717203099 57.1446680819023, -2.09796115562555 57.1448677424633, -2.09554608763705 57.1455415280263, -2.08978761299588 57.1409403132676, -2.08967555316753 57.1403717746151, -2.0882120280466 57.1405470942304, -2.07571111447462 57.1406560085666, -2.07235431383438 57.1418419845685, -2.06920884418592 57.1421474254686, -2.06521179825409 57.144067469068, -2.06100565229879 57.1456928396051, -2.01877021137073 57.1461574324006, -2.01746715794123 57.1443574286352, -2.01615980697691 57.1399056220016, -2.01632663387332 57.1358955754923, -2.01723932071019 57.1301507994778)))',4326);  
set @l = geography::STPointFromText('POINT (-2.0535344529468018 57.140210162062083)',4326);  

select @l.STContains(@p); 

Я ожидаю, что оператор select вернет 1.

Еще более странно то, что когда я пытаюсь провести эту точку по всей моей таблице полигонов:

select polygon_id from polygons where polygon.STcontains(@l)=1

Он возвращает 246 результатов из 343 полигонов.

Я пробовал STContains, STWithin и STIntersects, и все они дали одинаковые результаты.

У меня такое чувство, будто я упускаю что-то очень элементарное или QGIS мне врет. Может ли кто-нибудь сказать мне, где я ошибаюсь?

Он перевернут Learn.microsoft.com/en-us/sql/relational-databases/spatial/… вам нужно использовать правило левой руки для рисования многоугольников. Вы можете инвертировать их, используя .ReorientObject()

Charlieface 24.06.2024 13:01

Полигоны в пространственных данных SQL Server имеют требования к кольцевому порядку, извилистости или направленности: считается, что внутренняя часть многоугольников находится на левой стороне сегментов линий, поэтому точки следует указывать против часовой стрелки. Также вы, вероятно, захотите проверить @Polygon.STContains(@Point).

AlwaysLearning 24.06.2024 13:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

SQL Server требует, чтобы полигоны в geography использовали правило левой руки, что означает, что если вы хотите заключить многоугольник, вам нужно «пройти» по нему так, чтобы внутренняя его часть находилась слева от вас, а внешняя часть — слева. верно.

Ваши данные перевернуты, они охватывают внешнюю часть многоугольника. Вы также звоните StContains не по тому экземпляру, вам нужно вызвать @p и передать @l. Вы можете переориентировать многоугольник, используя ReorientObject()

declare @p geography   
declare @l geography      

set @p = geography::STMPolyFromText('MULTIPOLYGON (((-2.01723932071019 57.1301507994778, -2.05959736945859 57.1308481812907, -2.06094305103518 57.1309872145762, -2.06442332315307 57.1311592624651, -2.06738702460041 57.131260961538, -2.06834761818132 57.1312257047487, -2.07352085461956 57.1308074773011, -2.08662715692557 57.1284264355531, -2.08835456332902 57.1282051063708, -2.0891720244275 57.1281861098907, -2.09070679418533 57.1283121889021, -2.09310621355588 57.1286955641499, -2.09502104689506 57.1293780321133, -2.09674004600622 57.1304564574772, -2.09753934746642 57.1297443781977, -2.09875197034386 57.1291864729083, -2.10340075289855 57.1282116756316, -2.10590378101433 57.1284283727703, -2.10916734028092 57.129042168269, -2.1099366825462 57.1291282326644, -2.11138826300974 57.1291886324809, -2.11294222137845 57.1287904597294, -2.11432776064015 57.1284126116958, -2.11590135588206 57.1272468512517, -2.11783267950974 57.1257414916239, -2.11972005111187 57.1230896037971, -2.12220448182387 57.1236735070728, -2.12237561434298 57.1239917795713, -2.12132109065263 57.1242488139312, -2.1173707565196 57.129607293332, -2.11658292484552 57.1328230202163, -2.11554089667428 57.1347555681128, -2.11504663847733 57.1359238965379, -2.11507076780594 57.1361851484318, -2.11527759405925 57.1364937439207, -2.11485673955606 57.1366369506911, -2.11452832733778 57.1372965941222, -2.1140394284489 57.1392757110769, -2.11377688986274 57.1399955310532, -2.11295601438074 57.1418667234446, -2.11208273346248 57.1427865720397, -2.10218925747153 57.1456872698938, -2.10042721504413 57.1441390669773, -2.09826717203099 57.1446680819023, -2.09796115562555 57.1448677424633, -2.09554608763705 57.1455415280263, -2.08978761299588 57.1409403132676, -2.08967555316753 57.1403717746151, -2.0882120280466 57.1405470942304, -2.07571111447462 57.1406560085666, -2.07235431383438 57.1418419845685, -2.06920884418592 57.1421474254686, -2.06521179825409 57.144067469068, -2.06100565229879 57.1456928396051, -2.01877021137073 57.1461574324006, -2.01746715794123 57.1443574286352, -2.01615980697691 57.1399056220016, -2.01632663387332 57.1358955754923, -2.01723932071019 57.1301507994778)))',4326);  
set @l = geography::STPointFromText('POINT (-2.0535344529468018 57.140210162062083)',4326);  

select @p.ReorientObject().STContains(@l);

db<>рабочий пример

Чтобы обновить всю таблицу, вы можете сделать

UPDATE YourTable
SET ThePolygons = ThePolygons.ReorientObject()
WHERE ThePolygons.STArea() >= 255030000000000;  -- more than half the world

Обратите внимание: если у вас действительно есть несколько полигонов в экземплярах Multipolgon (чего здесь нет), вам нужно будет разбить их и выяснить, правильно ли ориентирован каждый из них.

Большое вам спасибо за это! Я получил данные о полигонах из онлайн-источника и использовал QGIS для экспорта файла .shp в файл .csv. при этом по глупости полагая, что это позволит отметить точки в правильном порядке.

Just_Some_Guy 24.06.2024 13:44

Другие вопросы по теме