使用 ST_DWithin 获取区域内最近对象的 ID

Using ST_DWithin to get id of closest object within an area

我在 pgAdmin4 中有一个触发器函数,它可以在 QGIS 中抓取距离线的起点和终点最近的对象。但是,我不仅要获取最近对象的 id,而且只在对象在 20' 半径内并且对象的 id 不为 null 时才获取该 id。

This fiddle 有我的工作触发器(触发器的副本也可以在下面找到)以及一些示例数据。我知道我需要将 ST_DWithin 添加到函数中,但我不确定如何去做。

触发代码如下:

CREATE OR REPLACE FUNCTION insert_pipe() RETURNS TRIGGER AS $$
BEGIN
  SELECT 
  j.node_id,
  i.node_id
  INTO NEW.dwn_str, NEW.up_str
  FROM ST_Dump(ST_SetSRID(NEW.geom,2346)) dump_line,
  LATERAL (SELECT s.node_id,(ST_SetSRID(s.geom,2346)) 
           FROM structures s
           ORDER BY ST_EndPoint((dump_line).geom)<->(ST_SetSRID(s.geom,2346)) 
           LIMIT 1) j (node_id,geom_closest_downstream),
  LATERAL (SELECT s.node_id,(ST_SetSRID(s.geom,2346))
           FROM structures s
           ORDER BY ST_StartPoint((dump_line).geom)<->(ST_SetSRID(s.geom,2346)) 
           LIMIT 1) i (node_id,geom_closest_upstream);
           
  RETURN NEW;
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER t_insert_pipe 
BEFORE INSERT OR UPDATE ON pipes FOR EACH ROW EXECUTE PROCEDURE insert_pipe();

您很可能使用 ST_SetSRID 错误。顾名思义,它应该用于将 SRS 设置为错误或不存在的几何图形。但是,您的几何已经有一个 SRS,即 EPSG:2965。因此,如果您想使用不同的 SRS 执行空间操作,并且您可以负担得起查询时间的这种更改(请注意开销!),请在子查询的 WHERE 子句中使用 . Other than that, just place the

CREATE OR REPLACE FUNCTION insert_pipe() RETURNS TRIGGER AS $$
BEGIN
  SELECT 
  j.node_id,
  i.node_id
  INTO NEW.node_id_dwn_str, NEW.node_id_up_str
  FROM ST_Dump(ST_Transform(NEW.geom,2346)) dump_line,
  LATERAL (SELECT s.node_id,ST_Transform(s.geom,2346) 
           FROM structures s 
           WHERE ST_DWithin((dump_line).geom,ST_Transform(s.geom,2346),your_dist)
           ORDER BY ST_EndPoint((dump_line).geom)<->(ST_Transform(s.geom,2346)) 
           LIMIT 1) j (node_id,geom_closest_downstream),
  LATERAL (SELECT s.node_id,(ST_Transform(s.geom,2346))
           FROM structures s
           WHERE ST_DWithin((dump_line).geom,ST_Transform(s.geom,2346),your_dist)
           ORDER BY ST_StartPoint((dump_line).geom)<->(ST_Transform(s.geom,2346)) 
           LIMIT 1) i (node_id,geom_closest_upstream);
           
  RETURN NEW;
END; $$ LANGUAGE plpgsql;
  • 根据新 SRS 的单位将占位符 your_dist 更改为您想要的距离。
  • 考虑更新您的几何图形以使用“正确的”SRS,而不是在查询时进行更新。

进一步阅读:

原来是我对ST_DWithin()的误解导致了错误。离开这里一段时间后,我回来找到了解决方案。我使用 ST_Distance 而不是 ST_DWithin()。下面是代码。

BEGIN
  SELECT 
  j.node_id
  INTO NEW.dwn_str
  FROM ST_Dump(ST_SetSRID(NEW.geom,4326)) dump_line,
  LATERAL (SELECT s.node_id, 
                  ST_Distance(endpoint,ST_SetSRID(s.geom,4326)) as dist 
           FROM structures s,
                  Lateral (SELECT ST_EndPoint(ST_SetSRID(dump_line.geom,4326)) as endpoint
                          FROM ST_Dump(ST_SetSRID((NEW.geom),4326)) dump_line) l
           WHERE ST_Distance(endpoint, ST_SetSRID(s.geom,4326)) < '1'
           ORDER BY dist asc
           LIMIT 1) j;          
  
  RETURN NEW;
END;

我有两套这种扳机。一种用于上游,一种用于下游。 @JimJones 很接近,尽管 ST_DWithin() 的使用返回了一个布尔值并导致了问题。通过嵌套横向,我能够做我需要做的事情。