【问题标题】:postgresql postgis If point inside circlepostgresql postgis 如果点在圆圈内
【发布时间】:2017-06-09 05:37:41
【问题描述】:

我使用 postgresql 作为 db,我有一个名为 car_wash 的表,字段为“点几何”(使用 postgis),所以在应用程序中我使用 GOOGLE API 从用户那里得到 lon lat,下一步我需要创建圆圈用户并检查我是否在这个圈子内使用了 car_wash

  select *
 from car_wash cw
where
ST_DWithin (
   cw.lon_lat,
   ST_GeomFromText('POINT(54.21 22.54)')
)=false
AND
not cw.was_deleted

这是正确的方式吗?如果你需要我的 srid 根据这个查询是 0

 Select Find_SRID('public',  'car_wash',  'lon_lat')

【问题讨论】:

    标签: postgresql distance postgis


    【解决方案1】:

    首先 - 我假设 lat_long 是 georaphy 类型的列。如果它是几何类型列,您将不得不将我的示例修改为其他一些 EPSG(全世界可能是 3857 公制 EPSG)。这非常重要,因为 st_dwithin 以米为单位检查 geopraphy 类型,在地图单位中检查几何(对于 EPSG 4326,单位是度数而不是米)

    像这样插入你的数据

    insert into car_wash values (1,'aaa',st_setsrid(st_makepoint(54.51, 22.54),4326))
    

    我解释了为什么使用 st_setsrid、st_makepoint,以及 4326 到底是什么。 - 4326 是 EPSG 4326 - 它是最广为人知的坐标参考系统(您有纬度和经度的度数)。

    • st_makepoint - 将根据您的经纬度坐标创建地理点。它看起来像字节,但不用担心,如果由于某些原因需要 lat 和 long,您可以使用 st_x() 和 st_y() 或 st_astext() 函数获取它们。拥有 geoms 或 geogs (在这种情况下)的最好的事情是你可以使用 gist index。非常强大的工具,可以加快您的地理查询。

    • st_setsrid - st_makepoint 将创建点,但 srid=0。你必须告诉 POSTGIS 它应该在什么 EPSG 中读取你的数据。例如,如果你告诉他用 4326 阅读它,它将在谷歌世界地图上的正确位置,但如果你说例如 3857,它将在完全不同的位置,因为 3857 是公制而不是度数,所以它将在 50 左右距离左下角 50 米(或者可能是左上角,不记得了)

    在 geog 上创建索引

    create index on car_wash using gist (geog);
    

    我们有表格,里面有数据和索引。现在我们要检查您的点是否靠近您的任何洗车场。

    select *
      from car_wash cw
     where ST_DWithin (cw.geog,ST_GeogFromtext('SRID=4326;POINT(54.21 22.54)'),1000)
      AND cw.was_deleted=false
    

    在 ST_DWithin 中,第三个参数是以米为单位的距离(georpahy)或地图单位(几何)。因此,在这种情况下,它将向您显示距离您的用户位置最远 1000 米且未被删除的所有洗车场。

    【讨论】:

      【解决方案2】:

      在使用ST_DWithin 函数时,您的第三个参数必须是距离。 也可以在ST_GeomFromText中定义srid

      有两个简单的例子,你可以看到区别:

      select ST_DWithin(
      st_geomfromtext('POINT(54.51 22.54)',4326),
      st_geomfromtext('POINT(54.21 22.54)',4326),0.5
      )
      result is true
      
      select ST_DWithin(
      st_geomfromtext('POINT(54.51 22.54)',4326),
      st_geomfromtext('POINT(54.21 22.54)',4326),0.1
      )
      result is false
      

      来源:

      https://postgis.net/docs/ST_DWithin.html

      https://postgis.net/docs/ST_GeomFromText.html

      【讨论】:

      • 谢谢,但是如果两个点的 srid 为零,ST_DWithin 的第三个参数是米还是弧度的距离?
      • st_geomfromtext 总是返回几何图形。这意味着距离是米。所以你必须使用 st_geogfromtext (geography) 来获得真实的距离。有一个例子:select st_distance (st_geogfromtext('POINT(54.11 22.54)'),st_geogfromtext('POINT(54.21 22.54)')) 结果10286.66378146米
      • link ST_DWithin:几何单位是空间参考的单位(所以它会改变 srid),地理单位是米。我认为地理对你来说是更好的解决方案
      【解决方案3】:

      ST_GeomFromText('POINT(54.21 22.54)') 的 SRID 必须与 cw.lon_lat 的 SRID 相同。假设 cw.lon_lat 的 SRID 为 4326,您可以使用 ST_GeomFromText('POINT(54.21 22.54)',4326) 设置其他属性 srib。 其次,ST_DWithin 需要缓冲距离作为第三个参数。所以假设如果你想检查点是否在 100 米缓冲区内,它应该是这样的

      ST_DWithin (
         cw.lon_lat,
         ST_GeomFromText('POINT(54.21 22.54)', 3857), 100
      )
      

      缓冲区值根据 srid 单位。在 3857 的情况下,它的仪表。您需要使用 st_setSRID 将 cw.lon_lat 和 POINT(54.21 22.54) 转换为相同的 SRID 以使其正常工作,例如

      【讨论】:

      • 感谢您的回复,我能再问一个问题吗,为了从用户那里获取 lonLat,我使用了 hybernete,我没有得到 srid,所以所有 SRID 都是 0,ST_DWithin 是否将米作为参数或弧度?
      • 您必须知道参数的 srid 才能在 st_dwithin 中工作。您可能知道 lon_lat 的来源,然后您可以从那里检查他们正在使用的 srid。在谷歌的情况下,很可能是 4326。之后将两个参数的 srid 设置为相同。像 ST_DWithin ( st_setSRID(cw.lon_lat, 4326), ST_GeomFromText('POINT(54.21 22.54)', 4326), 100 )。
      • 在 4326 的情况下它的单位是度,在 3857 的情况下它的米。您可以搜索任何 srid 的单位
      • -1 因为您的代码将 3857 设置为 lat-long 中的一个点。您需要在 4326 中创建点,然后使用 st_transform 将其投影到 3857。您的第一条评论建议使用 100 度的缓冲区。
      猜你喜欢
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 2019-01-17
      • 2012-11-12
      • 1970-01-01
      • 2019-07-19
      相关资源
      最近更新 更多