SQL-сервер 2008+:Лучший способ определить, перекрываются ли два полигона?

StackOverflow https://stackoverflow.com/questions/8804722

Вопрос

У нас есть приложение, в котором есть база данных, полная полигонов (в настоящее время хранящихся в виде точек), которые приложение .net извлекает и проверяет, перекрываются ли они.

Мне пришло в голову, что было бы гораздо лучше преобразовать эти массивы точек в объекты полигонов/полилиний в базе данных и использовать sql, чтобы получить информацию о том, перекрываются они или нет.

Я видел различные методы, предложенные для этого, но ни один из приведенных примеров не полностью соответствовал моим потребностям.

Я был бы очень рад получить информацию от тех, кто достаточно любезен, чтобы поделиться своим опытом.

Дополнительный:

В ответ на вопросы:Это действительно 2D.и да, любое пересечение этих двух событий считается истинным.Многоугольники имеют n точек и могут быть вогнутыми.Полигоны будут сохранены по одному в каждой строке (после задачи преобразования данных) как полигоны (т. е.тип полигона..это можно было бы назвать чем-то другим пространственным/геомным, моя память сейчас не на моей стороне)

Это было полезно?

Решение

Вы можете использовать .stintersection с .stastext () для проверки перекрывающихся полигонов. (Я действительно ненавижу терминологию, которую использовала Microsoft (или тот, кто устанавливает стандартные термины). «Прикосновение», на мой взгляд, должно быть тестом на то, совпадают ли две формы геометрии/географии вообще, а не просто делиться границей.)

Тем не мение....

Если @radiusgeom - это геометрия, представляющая радиус из точки, следующее вернет список любых двух полигонов, где пересечение (геометрия, которая представляет область, где две геометрии перекрываются) не является пустым.

SELECT CT.ID AS CTID, CT.[Geom] AS CensusTractGeom
FROM CensusTracts CT
WHERE CT.[Geom].STIntersection(@RadiusGeom).STAsText() <> 'GEOMETRYCOLLECTION EMPTY'

Если ваше поле геометрии пространственно индексируется, это работает довольно быстро. Я запустил это на 66 000 рекордов США CT примерно за 3 секунды. Там может быть лучший способ, но, поскольку ни у кого больше не было ответа, это была моя попытка получить ответ для вас. Надеюсь, поможет!

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

Рассчитайте и сохраните ограничивающий прямоугольник каждого многоугольника в наборе новых полей в строке, который связан с этим многоугольником. (Я предполагаю, что у вас есть один; если нет, создайте его.) Когда ваше приложение Dotnet имеет многоугольник и ищет перекрывающиеся многоугольники, оно может извлечь из базы данных только те полигоны, ограничивающие прямоугольники, используя относительно простое утверждение SQL Select. Эти многоугольники должны быть относительно мало, так что это будет эффективно. Затем ваше приложение Dotnet может выполнить более тонкие расчеты перекрытия полигона, чтобы определить, какие из них действительно перекрываются.

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

MSSQL поддерживает интеграцию с CLR, начиная с версии 2005.Это означает, что вы можете определить свой собственный тип данных в сборке, зарегистрировать сборку в MSSQL, и с этого момента MSSQL будет принимать ваш определяемый пользователем тип данных как допустимый тип для столбца и вызывать вашу сборку. для выполнения операций с пользовательским типом данных.

Пример статьи об этой технике на CodeProject: Создание пользовательских типов данных в SQL Server 2005

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top