代码之家  ›  专栏  ›  技术社区  ›  Budgie

用Rails构造PostGIS查询

  •  3
  • Budgie  · 技术社区  · 15 年前

    我正在使用PostGIS(1.5.1)和Rails(3.0.0rc)以及Google地图(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\u适配器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
    
    3 回复  |  直到 15 年前
        1
  •  3
  •   Paul Ramsey    15 年前

        2
  •  1
  •   Community CDub    8 年前

    感谢所有的输入-我担心这实际上是我的一个巨大的n00b错误,在得到x/y和lng/lat之间的相关性时混淆了,因此为什么地图上的点在缩小时显示良好,但在放大时消失了。我完全推荐 QGIS (感谢 scw https://gis.stackexchange.com/

    顺便说一句,稍微令人惊讶的是,即使边界框与国际日期线相交,新西兰/澳大利亚的点也显示得很好,不过如果我在该区域添加更多的点,这种情况可能会改变。

        3
  •  0
  •   Preston Marshall    15 年前

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

    推荐文章