使用 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()
的使用返回了一个布尔值并导致了问题。通过嵌套横向,我能够做我需要做的事情。
我在 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
子句中使用
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()
的使用返回了一个布尔值并导致了问题。通过嵌套横向,我能够做我需要做的事情。