How to Use (Ruby) Rgeo to Transform (Unproject) Coordinates

How Can I Use (Ruby) RGeo to Transform (Unproject) Coordinates

As a wild stab in the dark, because I don't know RGeo or even Ruby, try substituting your coordinates in feet with their metres equivalent: 1832244.0944819663048746863094224, 640342.57048223700783128534419392 (you probably won't need that number of decimal places though...) Another possibility is to swap the coordinates around - maybe RGeo makes some unconventional assumptions.

If you are able to call executables from Ruby, you could simply use ogr2ogr to convert your shapefiles.

How can I transform the coordinates of a Shapefile?

The data you have from the shape file is projected geographic data.

From your question it sounds like you would really just prefer to have your data in lat/long. To get that you need to reproject your data. I am not a ruby guy, but a quick web search reveals that georuby does not support reprojection http://georuby.rubyforge.org/, however rgeo does. http://www.daniel-azuma.com/blog/archives/28

If you would like to know more about map projections have a look here.

By the way there is a stackexchange site for GIS (geographic information systems) experts called http://gis.stackexchange.com

RGeo Projected Buffer Polygon too small

What you're observing here is Mercator distortion. A distance of "50" in a mercator projection doesn't correspond to 50 meters on the real planet surface, unless you're at the Equator.

The circle drawn by your iOS map is correct: that's the 50 meter radius. What I suspect you did to create your second image was to project the point into a Mercator projection (according to the Proj4 you provided). Then you proceeded to create a buffer with radius 50 in the projected coordinate system. However, 50 Mercator units at latitude 40.61 corresponds to only about 37.96 meters in surface of the earth distance. So when you project that polygon back into latitude and longitude and plot it, that's what you see: a 38-meter circle.

One way to visualize this is to look at the full world map on Google Maps. Draw a circle of radius 50 pixels at the equator. And then draw another circle of radius 50 pixels over Greenland. On the map (in Mercator coordinates), those circles are the same size. But, if you know your Mercator projection, you know it distorts Greenland because Greenland is far away from the Equator, so your circle over Greenland is actually much smaller in real life than your circle above the equator. At 40 degrees latitude, the distortion isn't as severe, but it still is there.

If you want to correct this, it's pretty easy. The size distortion caused by the Mercator projection is proportional to the secant of the latitude. That is, 50 mercator units on the equator equals 50 meters, but 50 mercator units at latitude x (in radians), corresponds to 50 / sec(x) meters. So if you want a radius of 50 meters, multiply 50 by sec(latitude), and use that number as the radius in mercator coordinates. In RGeo-speak:

p_lonlat = GEOFACTORY.point(40.610355377197266, -75.38220214843749)
p_proj = p_lonlat.projection
buf_proj = p_proj.buffer(50.0 * (1 / Math.cos(p_lonlat.y / 180.0 * Math::PI)))
buf_lonlat = GEOFACTORY.unproject(buf_proj)

Storing Google Maps geo data with Rails / PostGIS / RGeo

Found my answer here: Simple Mercator Factory Project/Unproject - Google Groups

The problem was I was using a different factory instance for the properties than what was being used by the ActiveRecord adapter. The solution is to create a single instance of the simple mercator factory in the initializer.

Location class:

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

initializers/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

Getting InvalidGeometry: LinearRing failed ring test after upgrading rgeo gem

This doesn't appear to be an issue with the rgeo gem but rather the underlying geos library on your mac.

There appears to be a difference in the way that geos 3.8.x (3.8.1 is the latest version in Homebrew circa 4/13/2020) and earlier versions of the geos library handle the is_simple calculation that determines Polygon validity. This affects any RGeo factory (most of them but not RGeo::Geographic.spherical_factory or RGeo::Cartesian.simple_factory) backed by the CAPI.

If you download version 3.5.x of geos from https://trac.osgeo.org/geos/ and build it with cmake (takes a while but installs cleanly) you should have consistent behavior between your production and local development environments.

If you were using the simple_mercator factory I doubt that differences in how spherical coordinates (implemented in pure ruby) are validated explain the differences in behavior that you see.

See this issue: https://github.com/rgeo/rgeo/issues/218



Related Topics



Leave a reply



Submit