Преобразование Polygon в MultiPolygon с помощью RGeo gem

У меня есть данные устаревших областей, где некоторые записи в формате Polygon, а некоторые в формате MultiPolygon хранятся в базе данных noSQL в формате JSON. Мне нужно перенести эти данные в базу данных PostGIS со столбцом area, который имеет тип ST_MultiPolygon.

Итак, мой вопрос: как я могу преобразовать Polygon области в MultiPolygon с помощью RGeo gem или чего-то подобного?

Прямо сейчас я конвертирую MultiPolygons следующим образом:

multipolygon = RGeo::GeoJSON.decode(location.area)
PostgisLocation.create(area: multipolygon)

Но когда область не мультиполигональная, а полигональная, БД выдает исключение: PG::InternalError: ERROR: parse error - invalid geometry

Пример текстового представления полигона:

POLYGON ((-6.00606009808446 54.5901007810674, -6.01003269079491 54.5928954129105, -5.97732358111394 54.5870863982436, -6.00606009808446 54.5901007810674))

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


person nattfodd    schedule 09.02.2018    source источник


Ответы (2)


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

poly_text = 'POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))'
factory = RGeo::Geos.factory(:srid => 4326)
polygon = factory.parse_wkt(poly_text)
puts factory.multi_polygon([polygon]).to_s
# MULTIPOLYGON (((0.0 0.0, 0.0 10.0, 10.0 0.0, 10.0 10.0, 0.0 0.0)))
person Cody Gustafson    schedule 21.02.2018

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

#used $factory as placeholder for whatever it is you're using
class ModelName << ActiveRecord::Base
  before_create do |r|
    if area.count > 1
      polygons = []
      area.each do |shp|
        polygons << shp
      end
      r.area = $factory.multi_polygon(polygons)
      r.save
    end
  end
  #....
end

Мой код не очень точен, и я даже не совсем уверен, что сам обратный вызов будет работать правильно, но я полагаю, что вы поняли суть. Конечно, вы можете просто использовать этот вид обработки исключений, прежде чем использовать метод #save или #create.

person boulder_ruby    schedule 15.05.2018