Ruby Rails Postgis - Нахождение всех точек в многоугольнике - PullRequest
6 голосов
/ 25 января 2012

Мне нужна помощь по созданию sql-запросов для использования в rails с activerecord-postgis-adapter. Я много читал, но сейчас немного застрял, любая помощь будет высоко ценится.

У меня есть две модели событий и областей:

События имеют столбец геометрии типа Point

class Event < ActiveRecord::Base
  self.rgeo_factory_generator = RGeo::Geos.factory_generator    
end

t.spatial  "geometry", :limit => {:srid=>4326, :type=>"polygon", :geographic=>true}

Области имеют столбец 'geometry' типа Polygon

class Area < ActiveRecord::Base 
  self.rgeo_factory_generator = RGeo::Geos.factory_generator
end

t.spatial  "geometry", :limit => {:srid=>4326, :type=>"point", :geographic=>true}

Я могу создавать и отображать как события, так и области на карте Google, а также создавать области, нажимая на карту и сохраняя в базе данных.

Я хочу выполнить следующие 2 запроса:

  1. @area.events - показывать все события в области
  2. @event.areas - показать все области, в которых находится одно событие

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

Большое спасибо

Ответы [ 2 ]

6 голосов
/ 30 января 2012

Вот быстрый способ сделать это. Они просто возвращают массивы объектов ActiveRecord.

class Area
  def events
    Event.joins("INNER JOIN areas ON areas.id=#{id} AND st_contains(areas.geometry, events.geometry)").all
  end
end

class Event
  def areas
    Area.joins("INNER JOIN events ON events.id=#{id} AND st_contains(areas.geometry, events.geometry)").all
  end
end

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

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

Правильно двенадцатое: вы должны создать пространственные индексы для обеих таблиц. Activerecord-postgis-adaptor должен сделать это простым в вашей миграции.

change_table :events do |t|
  t.index :geometry, :spatial => true
end

change_table :areas do |t|
  t.index :geometry, :spatial => true
end

Если у вас возникли проблемы с установкой postgis, я недавно написал несколько записей в блоге на эту тему. Проверьте http://www.daniel -azuma.com / блог / архив / категория / технология / георали . Я также являюсь автором rgeo и activerecord-postgis-adaptor, поэтому я с радостью помогу, если вы застряли на вещах.

3 голосов
/ 26 января 2012

Этот ответ будет для вас небольшой работой.Я слаб с рубином на рельсах, но я должен быть в состоянии помочь вам через раздел БД.

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

Select *
from area a inner join event e on 1=1

Это создаст списоккаждая область, присоединенная к каждому событию ... если у вас есть 500 событий и 20 областей, этот запрос вернет 10'000 строк.Теперь вы хотите отфильтровать это так, чтобы только события, которые находятся в области, к которой они были присоединены.Для этого мы можем использовать st_contains как st_contains (polygon, point):

where st_contains(a.polygon,e.point) = 't'

Если вы запустите это, он должен дать вам. , e. для всех событий в области.Теперь это просто вопрос подсчета того, что вы хотите считать.

select a.id, count(1)
from area a inner join event e on 1=1
where st_contains(a.polygon,e.point) = 't'
group by 1

Это даст вам список всех ваших районов (по идентификатору) и количество событий в них.Отключение a.id с помощью e.id даст список идентификаторов событий и числовых областей, в которых они находятся.

К сожалению, я не знаю, как выразить эти запросы в Ruby, но концепции БД, которые выВам нужно будет здесь ...

Из соображений скорости вы должны изучить индексирование GIStree, которое у Postgres ... индексированные полигоны работают экспоненциально лучше.

Редактировать:

PostGIS - это файл, который поставляется с Postgres, но не существует в стандартной установке ... вам нужно найти этот файл.Они установят ряд ГИС-функций в вашей базе данных, включая ST_Contains.(функции находятся в базе данных, поэтому убедитесь, что вы устанавливаете функции в используемой вами БД)

Второе, что устанавливает файлы вклада PostGIS, - это база данных template_postGIS, которая требуется для типов данных geometry (geom кактип данных не будет существовать, пока он не будет установлен).

...