【问题标题】:Constucting a PostGIS query with Rails使用 Rails 构建 PostGIS 查询
【发布时间】:2011-04-03 02:53:12
【问题描述】:

我将 PostGIS (1.5.1) 与 Rails (3.0.0rc) 和 Google Map (v3) 一起使用,我正在寻找一种方法来查询数据库以检索多边形内的所有点(特别是,地图视口的边界)。目前我正在将边界坐标发送到服务器,如下所示:

google.maps.event.addListener(map, 'bounds_changed', function() {
  var bounds = map.getBounds();
  var ne = bounds.getNorthEast();
  var sw = bounds.getSouthWest();
  var yMaxLat = ne.lat();
  var xMaxLng = ne.lng();
  var yMinLat = sw.lat();
  var xMinLng = sw.lng();
  //alert("bounds changed");
  updateMap(yMaxLat, xMaxLng, yMinLat, xMinLng);
});

function updateMap(yMaxLat, xMaxLng, yMinLat, xMinLng) {
  jQuery.getJSON("/places", { "yMaxLat": yMaxLat, "xMaxLng": xMaxLng, "yMinLat": yMinLat, "xMinLng": xMinLng }, function(json) {
    if (json.length > 0) {
      for (i=0; i<json.length; i++) {
        var place = json[i];
        var category = json[i].tag;
        addLocation(place,category);
      }
    }
  });
}

然后在我的控制器中:

format.js do
  xMinLng = params[:xMinLng]
  yMinLat = params[:yMinLat]
  xMaxLng = params[:xMaxLng]
  yMaxLat = params[:yMaxLat]

  @map_places = Place.find(:all, :conditions => ["geom && ?", Polygon.from_coordinates([[[xMinLng, yMinLat], [xMinLng, yMaxLat], [xMaxLng, yMaxLat], [xMaxLng, yMinLat], [xMinLng, yMinLat]]], 4326)])
  render :json => @map_places
end

我的查询基于this example,但它的表现并不像预期的那样 - 地图缩小时会显示大多数点,但不会显示靠近国际日期变更线的点(即在澳大利亚)和新西兰)。放大地图时,对于全球的任何区域,这些点根本不会显示。我读过一些关于 PostGIS 的地理类型更适合这种查询的内容,但我不认为 GeoRuby 支持这种类型(GeoDjango 支持它)。我的控制台针对此类请求的输出如下:

Started GET "/places?yMaxLat=63.93767251746141&xMaxLng=43.033828125&yMinLat=36.88016688406946&xMinLng=-39.407578125" for 127.0.0.1 at Tue Aug 24 12:11:41 +0100 2010
Processing by PlacesController#index as JSON
Parameters: {"xMinLng"=>"-39.407578125", "yMaxLat"=>"63.93767251746141", "xMaxLng"=>"43.033828125", "yMinLat"=>"36.88016688406946"}
Place Load (0.4ms)  SELECT "places".* FROM "places"
Place Load (0.8ms)  SELECT "places".* FROM "places" WHERE (geom && '0103000020E6100000010000000500000052B81E852BB443C0DF0CF74EA970424052B81E852BB443C0686D2EA705F84F40AE47E17A54844540686D2EA705F84F40AE47E17A54844540DF0CF74EA970424052B81E852BB443C0DF0CF74EA9704240')
Completed 200 OK in 136ms (Views: 3.4ms | ActiveRecord: 1.2ms)

构建此类查询的最佳方法是什么?我在我的项目中使用了 GeoRuby 和 spatial_adapter gems,但我很难找到很多关于使用它们的信息,就像我上面描述的那样。距离查询可能是更好的方法吗?谢谢!

编辑:我的迁移如下:

class CreatePlaces < ActiveRecord::Migration
  def self.up
    create_table :places do |t|
      t.string :city_name
      t.integer :country_id, :null => false
      t.point :geom, :null => false, :with_z => true, :srid => 4326
      t.string :name, :null => false
      t.string :tag, :null => false

      t.timestamps
    end
add_index :places, :geom, :spatial => true
  end

  def self.down
    drop_table :places
  end
  remove_index :places, :geom
end

【问题讨论】:

    标签: ruby-on-rails postgis


    【解决方案1】:

    可能有两种不同类型的投影正在进行。确保数据库和您的应用程序中的投影相同。

    【讨论】:

    • 感谢您的回复,我在上面包含了我的数据库迁移以提供更多详细信息...
    • 嗯,它看起来像是一个有效的 SRID。您是否检查过这些点是否真的从 SQL 选择中显示出来?我会尝试将问题缩小到数据库或谷歌地图。我发现了一些 GMap 不会将点放在地图上某个位置的情况。
    • 英国和非洲的点显示良好,但仅在一定的缩放级别 - 大约 3 及以下。新西兰和澳大利亚的点从未出现,但我假设这可能是日期变更线问题......谷歌地图似乎发送边界很好,我认为这是我的查询有问题 - 如果我将所有点呈现为 JSON (所以没有查询)它们完美地显示在地图上!
    • 嗯,查询可能有问题,但它似乎适用于其他人。也许您可以尝试使用普通 sql 而不是 GeoRuby 进行查询,至少看看它返回什么?这是上面的文档:postgis.refractions.net/documentation/manual-1.5/…
    【解决方案2】:

    拿出一张标准的世界地图(中间是零经度,边缘是日期线)。在地图上绘制方框的角点。连接这些点,只使用留在地图内的线。那是查询数据库的框。这就是为什么您的澳大利亚/新西兰积分没有从查询中出来的原因。您必须使用地理类型或注意您的框何时跨越日期线并将其拆分为两个非交叉查询框。

    【讨论】:

      【解决方案3】:

      感谢所有输入 - 恐怕这实际上是我的一个巨大的 n00b 错误,因为混淆了 x/y 和 lng/lat 之间的相关性,因此地图上的点显示缩小时很好,但放大时消失了。我会彻底推荐QGIS(感谢https://gis.stackexchange.com/ 上的scw 的建议)对于刚开始使用GIS 的任何人,当显示点时我立即看到了错误上下翻转!!再次感谢大家!

      顺便说一句,有点令人惊讶的是,即使边界框越过国际日期变更线,新西兰/澳大利亚的点也能正常显示,尽管如果我在该区域添加更多点,情况可能会改变。

      【讨论】:

        猜你喜欢
        • 2020-09-29
        • 2013-02-18
        • 2020-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多