2016-12-24 10 views
2

RGeo/RailsでGoogle Mapsジオデータを処理するためにDaniel Azuma's solutionを実装する際に問題が発生しました。Google MapsジオデータをRails/PostGIS/RGeoに保存

SETUP

場所テーブル:

create_table "locations", force: :cascade do |t| 
    t.string "name",   
    t.geometry "polygon", limit: {:srid=>3857, :type=>"polygon"} 
end 

場所クラス:

class Location < ActiveRecord::Base 

    # Create a simple mercator factory. This factory itself is 
    # geographic (latitude-longitude) but it also contains a 
    # companion projection factory that uses EPSG 3857. 
    FACTORY = RGeo::Geographic.simple_mercator_factory 

    # To interact in projected coordinates, 
    # just use the "polygon" attributes directly. 
    def polygon_projected 
    self.polygon 
    end 
    def polygon_projected=(value) 
    self.polygon = value 
    end 

    # To use geographic (lat/lon) coordinates, 
    # convert them using the wrapper factory. 
    def polygon_geographic 
    FACTORY.unproject(self.polygon) 
    end 
    def polygon_geographic=(value) 
    self.polygon = FACTORY.project(value) 
    end 

    def self.from_geojson(geojson) 

    location = Location.new 
    decoded_polygon = RGeo::GeoJSON.decode(geojson, json_parser: :json, geo_factory: RGeo::Geographic.simple_mercator_factory) 
    location.polygon_geographic = decoded_polygon 
    return location 

    end 

end 

イニシャライザ/ rgeo.rb:

そこでここでは、私は、Googleの地図から座標を含むにGeoJSON形状から新しいLocationオブジェクトを作成GO-

herehere由来ソリューション)

ISSUE

RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config| 
    # By default, use the GEOS implementation for spatial columns. 
    config.default = RGeo::Geos.factory_generator 
end 

manhattan_polygon_data = '{"type":"Polygon","coordinates":[[[-73.9784998975546,40.7367992185915],[-73.9808911983494,40.7334453322506],[-73.9899687850649,40.7350399153528],[-73.9894998975546,40.7395992185915]]]}' 
location = Location.from_geojson(manhattan_polygon_data) 

この時点で、すべてのジオプロパティが正常に動作しています:

# Test geo properties: 
location.polygon_projected 
=> #<RGeo::Geos::CAPIPolygonImpl:0x3fc428c0c7dc "POLYGON ((-8235248.938246019 4973596.780357394, -8235515.136632829 4973104.057720993, -8236525.648963631 4973338.316345756, -8236473.452644745 4974008.150049943, -8235248.938246019 4973596.780357394))"> 
location.polygon_geographic 
=> #<RGeo::Geographic::ProjectedPolygonImpl:0x3fc425d137a0 "POLYGON ((-73.9784998975546 40.73679921859151, -73.9808911983494 40.73344533225058, -73.9899687850649 40.73503991535281, -73.9894998975546 40.73959921859151, -73.9784998975546 40.73679921859151))"> 

しかし、我々は保存し、データベースから再読み込みするとき、何かがうまくいかない:後者unproject操作が失敗した理由を

# Save and retrieve from DB: 
location.save! 
location_from_db = Location.find(location.id) 

# Test geo properties again: 
location_from_db.polygon_projected 
=> #<RGeo::Geos::CAPIPolygonImpl:0x3fc425cfb664 "POLYGON ((-8235248.938246019 4973596.780357394, -8235515.136632829 4973104.057720993, -8236525.648963631 4973338.316345756, -8236473.452644745 4974008.150049943, -8235248.938246019 4973596.780357394))"> 
location_from_db.polygon_geographic 
RGeo::Error::InvalidGeometry: You can unproject only features that are in the projected coordinate space. 
    from /usr/local/lib/ruby/gems/2.3.0/gems/rgeo-0.5.3/lib/rgeo/geographic/factory.rb:270:in `unproject' 

は、両方のオブジェクトの投影ジオメトリが等価であることを考えると、私はよく分かりません。

答えて

1

は、ここに私の答えが見つかりました:Simple Mercator Factory Project/Unproject - Google Groups

問題は、私はActiveRecordのアダプタが使用されていたものとは性質のために異なるファクトリインスタンスを使用していたでした。これを解決するには、イニシャライザに単純なメタファーファクトリの単一インスタンスを作成します。

Locationクラス:

class Location < ActiveRecord::Base 

    # To interact in projected coordinates, 
    # just use the "polygon" attributes directly. 
    def polygon_projected 
    self.polygon 
    end 
    def polygon_projected=(value) 
    self.polygon = value 
    end 

    # To use geographic (lat/lon) coordinates, 
    # convert them using the wrapper factory. 
    def polygon_geographic 
    FACTORY.unproject(self.polygon) 
    end 
    def polygon_geographic=(value) 
    self.polygon = FACTORY.project(value) 
    end 

    def self.from_geojson(geojson) 

    location = Location.new 
    decoded_polygon = RGeo::GeoJSON.decode(geojson, json_parser: :json, geo_factory: RGeo::Geographic.simple_mercator_factory) 
    location.polygon_geographic = decoded_polygon 
    return location 

    end 

end 

初期化子/ rgeo.rb:

# Create a single instance of simple mercator factory. 
# This factory itself is geographic (latitude-longitude) 
# but it also contains a companion projection factory that uses EPSG 3857. 
FACTORY = RGeo::Geographic.simple_mercator_factory 

RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config| 
    config.default = FACTORY.projection_factory 
end