【问题标题】:ST_Buffer equivalent for Circle based searches in MySQL?ST_Buffer 等效于 MySQL 中基于 Circle 的搜索?
【发布时间】:2009-12-28 20:56:10
【问题描述】:

我需要使用 MySQL GIS 搜索具有在指定圆内的点的行。伪代码示例查询为:

select * from gistable g where isInCircle(g.point, circleCenterPT, radius)

看来 PostGIS 可以通过 ST_Buffer 函数来做到这一点。 MySQL GIS 是否提供类似的功能?

【问题讨论】:

    标签: mysql gis postgis


    【解决方案1】:

    据我所知,MySQL 中的缓冲函数是not yet implemented

    这些功能是不 在 MySQL 中实现。他们可能会 出现在未来的版本中。

    * Buffer(g,d)
    
      Returns a geometry that represents all points whose distance from the geometry value g is less than or equal to a distance of d.
    

    如果我正确理解您的问题,您甚至可能不需要空间函数来执行此查询,您可以使用“常规”SQL 查询和Euclidean distance

    select * 
    from gistable g 
    where SQRT(POW(circleCenterPT.x - point.x,2) + POW(circleCenterPT.y - point.y,2)) < radius
    

    希望这会有所帮助。


    编辑: 性能肯定是这个查询的一个问题。

    关于 MySQL 中的空间函数,最新的快照似乎包括了新的函数,如 Buffer 或 Distance。 您可能想尝试一下:

    【讨论】:

    • 确实,将公式放入查询中会起作用......但也会非常慢(表扫​​描)。添加边界矩形会有所帮助,但我宁愿数据库为我处理这些细节。 :) 不过,我认为 MySQL 还没有提供帮助的功能。
    【解决方案2】:

    即使你使用PostGIS,你也不需要使用ST_Buffer函数,但是ST_Expand执行的操作相当于这个(伪代码):

    -- expand bounding box with 'units' in each direction
    envelope.xmin -= units;
    envelope.ymin -= units;
    envelope.xmax += units;
    envelope.ymax += units;
    -- also Z coordinate can be expanded this way
    

    在 PostGIS 语法中,SQL 查询通常如下所示:

    SELECT AsText(geom) FROM mypoints
    WHERE
      -- operator && triggers use of spatial index, for better performance
      geom && ST_Expand(ST_GeometryFromText('POINT(10 20)', 1234), 5) 
    AND
      -- and here is the actual filter condition
      Distance(geom, ST_GeometryFromText('POINT(10 20)', 1234)) < 5
    

    在 postgis-users 邮件列表中查找 Buffer vs Expand 解释。

    因此,理想情况下是使用 MySQL 复制类似的行为。我根本不是MySQL专家,但我想即使没有ST_Expand函数也是可行的。

    下面是模拟ST_Expand函数的方法:

    CONCAT('POLYGON((',
        X(GeomFromText('POINT(10 20)')) - 5, ' ', Y(GeomFromText('POINT(10 20)')) - 5, ',',
        X(GeomFromText('POINT(10 20)')) + 5, ' ', Y(GeomFromText('POINT(10 20)')) - 5, ',',
        X(GeomFromText('POINT(10 20)')) + 5, ' ', Y(GeomFromText('POINT(10 20)')) + 5, ',',
        X(GeomFromText('POINT(10 20)')) - 5, ' ', Y(GeomFromText('POINT(10 20)')) + 5, ',',
        X(GeomFromText('POINT(10 20)')) - 5, ' ', Y(GeomFromText('POINT(10 20)')) - 5, '))'
    );
    

    然后将这个结果与这样的查询结合起来:

    SELECT AsText(geom) FROM mypoints
    WHERE
      -- AFAIK, this should trigger use of spatial index in MySQL
      -- replace XXX with the of expanded point as result of CONCAT above
      Intersects(geom, GeomFromText( XXX ) )
    AND 
      -- test condition
      Distance(geom, GeomFromText('POINT(10 20)')) < 5
    

    如果您使用的是较旧的 MySQL 版本,而距离函数不可用,那么您可以只使用 amercader 使用基于 SQRT 的计算。

    我希望它能给你一些想法。

    【讨论】:

      【解决方案3】:

      从 MySQL 5.7.6 开始。
      ST_Distance_sphere(g1, g2[, radius])

      返回球体上两点和/或多点之间的最小球面距离,以米为单位,如果任何几何参数为 NULL 或为空,则返回 NULL

      计算使用球形地球和可配置的半径。可选的半径参数应以米为单位。如果省略,则默认半径为 6,370,986 米。如果半径参数存在但不是正数,则会发生 ER_WRONG_ARGUMENTS 错误

      编辑:为什么投反对票?

      SELECT *
      FROM gistable g
      WHERE ST_Distance_Sphere(g.point, circleCenterPT) <= radius
      

      【讨论】:

        猜你喜欢
        • 2015-05-31
        • 1970-01-01
        • 2012-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-12
        • 2012-11-11
        • 1970-01-01
        相关资源
        最近更新 更多