点多边形rgeo

时间:2017-10-20 01:25:14

标签: ruby-on-rails ruby geos rgeo

我需要知道一个点是否在多边形中,在我的rails应用程序中,为了我想使用rgeo gem。

要安装此geme,我按照rgeo git

上的说明进行操作

然后我确信GEOS和Proj4已正确安装。

enter image description here

我还添加了这个宝石'ffi-geos',没有特别的原因,只是跟着rgeo doc

最后,我在rails控制台上进行了测试以检查是否正常工作

  1. poly_text =“POLYGON ...”(很多要点,我知道第一点和最后一点是相同的,否则我认为这个算法是有效的,因为需要是一个封闭的多边形)
  2. factory = RGeo :: Cartesian :: Factory(我正在使用笛卡尔工厂,因为根据我的调查,如果我使用球形工具,这个工作量)
  3. poly = factory.new()。parse_wkt(poly_text)
  4. point1 = factory.new()。parse_wkt(“POINT(0 0)”)(此点不属于多边形)
  5. poly.within?(点1)
  6. result:RGeo :: Error :: UnsupportedOperation:Method Geometry#contains?没有定义的。     来自(irb):26
  7. 在这里你可以看到输出: enter image description here

    更多信息: rails版本5.1.2 ide c9 os ubuntu

    如果有人有解决方案,提前谢谢,我也愿意使用其他宝石,或者其他什么,我的目标是解决我的点/多边形问题。

3 个答案:

答案 0 :(得分:3)

您可以使用Geokit,只需在您的Gemfile中包含gem 'geokit'

然后,您需要创建一个点数组,其中每个点都是Geokit::LatLng

例如:

points = []
points << Geokit::LatLng.new("-34.8922513", "-56.1468951")
points << Geokit::LatLng.new("-34.905204", "-56.1848322")
points << Geokit::LatLng.new("-34.9091105", "-56.170756")
polygon = Geokit::Polygon.new(points)
polygon.contains? polygon.centroid #this should return true

不要担心第一个点是否与上一个点相同,new已经处理了这个问题,因为源代码中解释了here

答案 1 :(得分:1)

我在安装GEOS之前安装了gem。卸载然后再次安装rgeo gem。

答案 2 :(得分:0)

如果只需要多边形中的点,则无需使用完整的库。这非常简单,您可以自由抓取Geokit的实现(MIT许可):

def initialize(points)
    @points = points

    # A Polygon must be 'closed', the last point equal to the first point
    # Append the first point to the array to close the polygon
    @points << points[0] if points[0] != points[-1]
end

def contains?(point)
    last_point = @points[-1]
    oddNodes = false
    x = point.lng
    y = point.lat

    @points.each do |p|
        yi = p.lat
        xi = p.lng
        yj = last_point.lat
        xj = last_point.lng
        if yi < y && yj >= y ||
           yj < y && yi >= y
            oddNodes = !oddNodes if xi + (y - yi) / (yj - yi) * (xj - xi) < x
        end
        last_point = p
    end

    oddNodes
end

您可以找到完整的源代码here。当然,您必须创建自己的类并稍稍更改代码。