DbGeography - выберите многоугольники / линии линий, содержащиеся внутри многоугольника

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

Вот как я создаю прямоугольник области просмотра пользователей:

DbGeography viewport_rectangle = DbGeography.FromText(string.Format("POLYGON(({0} {1}, {0} {2}, {3} {2}, {3} {1}, {0} {1}))", lon_min, lat_min, lat_max, lon_max));

Затем я хочу выделить все объекты (Точки, Полилинии, Полигоны, расположенные внутри этого прямоугольника):

var objects = db.mapobjects.Where(x => !x.LocationGeographic.Intersects(viewport_rectangle));

Все пока здесь работает нормально. Проблема возникает, если PolyLine/Polygon не полностью содержится внутри полигона области просмотра. В этом случае это игнорируется, и я получаю "нет объектов" вместо объектов, где некоторые точки / ребра находятся вне области просмотра.

Есть ли альтернатива "Пересекающимся"? Я хочу выбрать объекты, содержащиеся в прямоугольнике области просмотра, независимо от того, находятся ли они вообще внутри или если только одна небольшая часть из них находится внутри прямоугольника области просмотра.

viewport_rectangle = {SRID = 4326; POLYGON ((15.693584159016611, 46.532346466357438, 15.693584159016611 46.532770863495614, 15.695530101656916 46.532770863495614, 15.695530101656916 46.532346435153838383838383838383838383838383835387438743838383838387474

Объект, который только частично находится внутри viewport_rectangle и должен быть возвращен в результате:

LINESTRING (15,694189164787527 +46,532622094224166, 15,694309193640944 +46,532614944062828, +15,694392677396532 46,5326121762582, 15,694401059299702 +46,532662919320614, 15,694536175578829 46,532621632923423, 15,694564338773485 +46,532659690218026, 15,694584455341097 46,532614944062828, 15,694570373743769 46,532578039989573, +15,694489236921068 46,53258611275777, +15,694502312690016 +46,532539290685662, 15,694723930209872 +46,53252614359414, +15,69474438205361 +46,532575041532539, +15,694786962121723 +46,532516225610692, 15,694763492792843 46,532481858630774, +15,694699790328738 46,532507922181281, 15,694884862750767 +46,532493852478581, 15.694849658757446 46.53254505695287)

Одна часть сгенерированного запроса LINQ:

SELECT [Filter1]. [ObjectId] AS [ObjectId], [Filter1]. [LocationGeographic] AS [LocationGeographic], FROM (SELECT [Extent1]. [ObjectId] AS [ObjectId], [Extent1]. [LocationGeographic] AS [LocationGeographic ] FROM [dbo]. [Mapobjects] AS [Extent1] WHERE (([Filter1].[LocationGeographic].STIntersects(@p__linq__0)) <> приведение (1 как бит))) AS [Project1]

Отредактировано: правильный порядок viewport_rectangle должен быть:

DbGeography viewport_rectangle = DbGeography.FromText(string.Format("POLYGON(({0} {1}, {2} {1}, {2} {3}, {0} {3}, {0} {1}))", lon_min, lat_min, lon_max, lat_max));

1 ответ

Решение

Похоже, у вас есть проблема ориентации кольца с вашим полигоном. Порядок, в котором вы указываете свои баллы, имеет значение. Полигон, как вы его определили, представляет собой весь глобус за вычетом очень маленького квадрата (предположительно, желаемый видовой экран). Как я это определил?

declare @line geography = geography::STGeomFromText('LINESTRING (15.694189164787527 46.532622094224166, 15.694309193640944 46.532614944062828, 15.694392677396532 46.5326121762582, 15.694401059299702 46.532662919320614, 15.694536175578829 46.532621632923423, 15.694564338773485 46.532659690218026, 15.694584455341097 46.532614944062828, 15.694570373743769 46.532578039989573, 15.694489236921068 46.53258611275777, 15.694502312690016 46.532539290685662, 15.694723930209872 46.53252614359414, 15.69474438205361 46.532575041532539, 15.694786962121723 46.532516225610692, 15.694763492792843 46.532481858630774, 15.694699790328738 46.532507922181281, 15.694884862750767 46.532493852478581, 15.694849658757446 46.53254505695287)', 4236),
    @poly geography = geography::STGeomFromText('POLYGON ((15.693584159016611 46.532346466357438, 15.693584159016611 46.532770863495614, 15.695530101656916 46.532770863495614, 15.695530101656916 46.532346466357438, 15.693584159016611 46.532346466357438))', 4236);

select @poly.EnvelopeAngle(); --returns 180
select @poly.ReorientObject().STIntersects(@line); --returns 1

Лучше всего, вы читаете на EnvelopeAngle() метод себя. Но я скажу это - я использую это как быструю эвристику, чтобы обнаружить проблему ориентации кольца, которая у вас здесь есть. Неизменно, если у многоугольника есть эта проблема, угол огибающей будет 180 (что почти никогда не то, что вы предполагали).

Я также рассказал о том, как это исправить, в приведенном выше коде; призвание ReorientObject() на многоугольнике меняется по часовой стрелке на против часовой стрелки (и наоборот).

Наконец, похоже, что строка строки полностью содержалась в вашем окне просмотра; Я проверял с STContains(), Что объясняет, почему вы ошибались раньше, когда то, что вы считали своим окном просмотра, было всем, кроме окна просмотра!

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