Получить полигоны, близкие к lat, длинные в MySQL

кто-нибудь знает способ получить все полигоны в БД MySQL на заданном расстоянии от точки? Фактическое расстояние не так важно, поскольку оно вычисляется для каждого найденного многоугольника позже, но было бы огромной оптимизацией просто сделать этот расчет для полигонов, которые "близки".

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

какие предложения?

3 ответов


медленная версия (без пространственных индексов):

SELECT  *
FROM    mytable
WHERE   MBRIntersects(mypolygon, LineString(Point(@X - @distance, @Y - @distance), Point(@X + @distance, @Y + @distance))

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

затем создать SPATIAL INDEX на поле, которое содержит координаты вершин и просто выдает этот запрос:

SELECT  DISTINCT polygon_id
FROM    vertices
WHERE   MBRContains(vertex, LineString(Point(@X - @distance, @Y - @distance), Point(@X + @distance, @Y + @distance))

вещи будут гораздо проще, если вы храните UTM координаты в вашей базе данных, а не широта и долгота.


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

первой идеей, которая приходит мне в голову, было бы использовать сетку, назначить каждую точку квадрату и проверить, выберите квадрат, в котором находится Точка, и те, кто вокруг него. Если мы говорим о бесконечных сетках, то используйте хэш-значение квадрата, это даст вам больше очков, чем нужно (где у вас есть столкновения), но все равно уменьшит сумму на кучу. Конечно, это не сразу применимо к полигонам, это просто мозговой штурм. Возможный подход, который может дать слишком много коллизий, был бы или все хэшированные значения вместе и выберите все записи, где хэши и это значение ненулевые (не уверен, что это возможно в MySQL), вы можете использовать большое количество битов.

проблема с этим подходом заключается в том, что мы говорим о сферической координаты (lat, long обычно) - это особенности, так как "квадраты" сетки сужаются по мере приближения к полюсам. Легкий подход к этому... не ставьте точки близко к полюсам... :)


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