使用 latitude/longitude 将 Rails 条记录过滤到地理多边形区域内
Filter Rails records to within geo-polygonal area using latitude/longitude
在我的 Rails 应用程序中,我有搜索区域,它们是地理多边形(使用 Google 地图 API 创建)。一旦绘制在地图上,搜索区域的坐标将作为哈希数组保存到记录中。它看起来像这样:
SearchArea.last.geo
=> [{"lat"=>"48.425555463221066", "lng"=>"-123.3793830871582"}, {"lat"=>"48.41336528699442", "lng"=>"-123.37800979614258"}, {"lat"=>"48.41006090395106", "lng"=>"-123.31672668457031"}, {"lat"=>"48.44696663691928", "lng"=>"-123.32067489624023"}]
我还有一些位置记录,它们的坐标被保存为一个散列,像这样:
Location.last.geo
=> {"lat"=>"28.8138124", "lng"=>"-96.9977682"}
我需要能够搜索 for/filter 地理坐标落在给定搜索区域内的记录。我没有地理空间编程方面的经验,所以我希望有人能在这里伸出援手。将不胜感激!
我调查过的内容:
- 我知道 Google 地图 API 有一个 Geometry Library。不幸的是,这是客户端。
- 我找到了 this answer, which led to this 篇文章,但是它是用 C 写的。
- This article 从 2009 年开始有一些代码看起来应该可以工作,但我不确定我将如何使用 latitude/longitude 坐标来实现它。
- This wiki page 有一大堆各种语言的光线投射实现,但同样,我不确定如何在 Ruby/Rails.
中实现它
Nate 在上面的评论中建议使用 PostGis,所以我同意了。
我最终使用 this tutorial 在我的 Rails 应用程序上安装了 PostGis,2016 年做了一些小改动:
- 它说添加
require 'active_record/connection_adapters/postgis_adapter/railtie'
的行实际上应该是 require 'active_record/connection_adapters/postgis_adapter'
- 创建地理 table 列的语法已从
t.point :latlon, :geographic => true
更改为 t.geography "latlon", limit: {:srid=>4326, :type=>"point", :geographic=>true}
基于this issue我还添加了以下初始化程序:
RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config|
config.default = RGeo::Geographic.spherical_factory(srid: 4326)
end
教程的其余部分是一个很好的参考,从安装 gem 到更新数据库配置。
从那里我可以创建一个带有 Point
:
的位置
Location.last.geo = "POINT(-123.366 48.428)"
以及我要使用 Polygon
:
在其中搜索的多边形区域
SearchArea.last.geo = "POLYGON((-123.382 48.426, -123.353 48.402, -123.314 48.423, -123.332 48.443, -123.382 48.426))"
最后,查询;原来如此简单!
sa = SearchArea.last
Location.where("ST_Intersects(geo, '#{sa.geo}')")
感谢内特的建议!
在我的 Rails 应用程序中,我有搜索区域,它们是地理多边形(使用 Google 地图 API 创建)。一旦绘制在地图上,搜索区域的坐标将作为哈希数组保存到记录中。它看起来像这样:
SearchArea.last.geo
=> [{"lat"=>"48.425555463221066", "lng"=>"-123.3793830871582"}, {"lat"=>"48.41336528699442", "lng"=>"-123.37800979614258"}, {"lat"=>"48.41006090395106", "lng"=>"-123.31672668457031"}, {"lat"=>"48.44696663691928", "lng"=>"-123.32067489624023"}]
我还有一些位置记录,它们的坐标被保存为一个散列,像这样:
Location.last.geo
=> {"lat"=>"28.8138124", "lng"=>"-96.9977682"}
我需要能够搜索 for/filter 地理坐标落在给定搜索区域内的记录。我没有地理空间编程方面的经验,所以我希望有人能在这里伸出援手。将不胜感激!
我调查过的内容:
- 我知道 Google 地图 API 有一个 Geometry Library。不幸的是,这是客户端。
- 我找到了 this answer, which led to this 篇文章,但是它是用 C 写的。
- This article 从 2009 年开始有一些代码看起来应该可以工作,但我不确定我将如何使用 latitude/longitude 坐标来实现它。
- This wiki page 有一大堆各种语言的光线投射实现,但同样,我不确定如何在 Ruby/Rails. 中实现它
Nate 在上面的评论中建议使用 PostGis,所以我同意了。
我最终使用 this tutorial 在我的 Rails 应用程序上安装了 PostGis,2016 年做了一些小改动:
- 它说添加
require 'active_record/connection_adapters/postgis_adapter/railtie'
的行实际上应该是require 'active_record/connection_adapters/postgis_adapter'
- 创建地理 table 列的语法已从
t.point :latlon, :geographic => true
更改为t.geography "latlon", limit: {:srid=>4326, :type=>"point", :geographic=>true}
基于this issue我还添加了以下初始化程序:
RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config| config.default = RGeo::Geographic.spherical_factory(srid: 4326) end
教程的其余部分是一个很好的参考,从安装 gem 到更新数据库配置。
从那里我可以创建一个带有 Point
:
Location.last.geo = "POINT(-123.366 48.428)"
以及我要使用 Polygon
:
SearchArea.last.geo = "POLYGON((-123.382 48.426, -123.353 48.402, -123.314 48.423, -123.332 48.443, -123.382 48.426))"
最后,查询;原来如此简单!
sa = SearchArea.last
Location.where("ST_Intersects(geo, '#{sa.geo}')")
感谢内特的建议!