1

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

这个小提琴有我的工作触发器(触发器的副本也可以在下面找到)以及一些示例数据。我知道我需要将 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();
4

2 回答 2

2

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

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;
  • 根据新的单位将占位符更改your_dist为所需的距离SRS
  • 考虑更新您的几何图形以使用“正确的”SRS,而不是在查询时进行。

进一步阅读:How to use ST_Transform

于 2021-07-20T16:06:38.383 回答
0

事实证明,我的误解ST_DWithin()是导致错误的原因。在花了一些时间之后,我回来并找到了解决方案。而不是ST_DWithin(),我使用 ST_Distance。下面是代码。

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()返回了一个布尔值并导致了问题。通过嵌套支管,我能够做我需要做的事情。

于 2021-08-19T18:17:30.237 回答