2

I have a legacy areas data, where some records are in Polygon and some in MultiPolygon format stored in noSQL DB in JSON format. I need to migrate that data to a PostGIS database with area column, which has type of ST_MultiPolygon.

So, my question is: how can I convert Polygon areas into MultiPolygon using RGeo gem or something similar?

Right now, I'm converting MultiPolygons like that:

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

But when area is not multipolygon, but polygon, DB throws exception: PG::InternalError: ERROR: parse error - invalid geometry

Example of polygon's text representation:

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

The stupidest thing that comes to my mind is to replace POLYGON with MULTIPOLYGON word, and add extra () parentheses. But, I believe there should be a better way to convert that using RGeo library. I spent some time reading documentation for RGeo but didn't find anything that could help me.

nattfodd
  • 1,790
  • 1
  • 17
  • 35

2 Answers2

2

You can build a multi polygon using an array of polygons. If you just pass in a single item you should get the results you want.

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)))
Cody Gustafson
  • 1,440
  • 11
  • 13
0

There are a ton of different ways to deal with this I'm sure, but maybe you could just use an ActiveRecord callback to deal with the exceptions?

#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

My code isn't very tight, and I'm not even entirely certain the callback itself would work correctly, but I suppose you get the gist. You could of course just use this kind of exception handling before you hit use the #save or #create method.

boulder_ruby
  • 38,457
  • 9
  • 79
  • 100