gpt4 book ai didi

postgresql - 如何找到接触开始/结束节点的 LINESTRING

转载 作者:行者123 更新时间:2023-11-29 11:47:44 28 4
gpt4 key购买 nike

在 PostGIS 中,您可以使用以下方法使两个几何相交:

geometry ST_Intersection (geometry geomA, geometry geomB);

在我的例子中,geomA 和 geomB 都是 LINESTRING,所以 ST_Intersection() 返回一个 POINT 几何体。

我想知道交点是发生在开始/结束节点(几何接触)还是中间(几何相交)。

我可以将 (Point.X, Point.Y) 与每个结束节点进行比较:

  • geomA.nodes(0) - geomA.nodes(len-1)
  • geomB.nodes(0) - geomB.nodes(len-1)

但是非常复杂。我想要一个简单的解决方案。

有3个相交的情况。

Example 1: Two lines in a "L" shape intersect in an end node on both lines on the bottom left.

Example 2: Two lines in a "T" shape where the vertical line intersects in the middle of the horizontal line. In this case the vertical line end node touches a non-end node of the horizontal line.

Example 3: Two lines in a "X" shape. Intersection point isn't an end node for either line.

对于我的问题,我只对找到类似示例 2 的感人场景感兴趣。

注意

这是我现在使用的伪代码。

geomM, geomN 线串
a, b, c, d, z 点。
(a,b) geomM ST_StartPoint(geom) 和 ST_EndPoint(geom)
的开始/结束节点(c,d) geomN 的开始/结束节点
z = ST_Intersect(geomM, geomN)

SELECT geomM, geomN, z
FROM Table
WHERE
(A and not ( B or C or D))
OR (B and not ( A or C or D))
OR (C and not ( A or B or D))
OR (D and not ( A or B or C))

A, B, C, D 替换 ( a=z ) ( b=z ) ( c=z ) ( d=z )
这意味着一个节点 {a,b,c,d} 等于交叉点 z。但只有一个
这将返回所有“T”形交叉点。

最佳答案

您需要 PostGIS 函数 ST_Touches() here .如果几何图形触及它们的边界,该函数返回 true,但如果它们相交,则返回 false。就您的示例而言,示例 1 和 2 返回 true,示例 3 返回 false

宽松的解决方案

要从单个表中选择所有接触 geometry(LINESTRING, xxx) 记录对的 ID,请使用:

SELECT x.id AS idA, y.id AS idB
FROM my_table x
JOIN my_table y ON ST_Touches(y.the_geom, x.the_geom)
WHERE x.id < y.id;

(WHERE 子句避免了重复的结果,例如 (132, 254)(254, 132)。)

请注意,线串也可以触及它们的任何非节点顶点。如果您想严格遵循示例 2,那么您必须将每个线串上的每个点与所有其他线串上的每个点进行比较,这显然是一个非常密集的操作。示例 2 基本上只有在您知道线串很短(最好是直线)时才可行。

严格解,仅限直线

如果所有 LINESTRING 都是直的,即仅由起始节点和结束节点组成,那么这就是您的解决方案:

SELECT h.id AS touched, v.id AS touching, ST_Intersection(h.the_geom, v.the_geom) AS touch_point
FROM my_table h -- "horizontal" T bar, being touched
JOIN my_table v ON -- "vertical" T bar, touching
(
-- The "vertical" start node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_StartPoint(v.the_geom))
) OR (
-- The "vertical" end node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_EndPoint(v.the_geom))
);

所有要求都在 JOIN ON 子句中检查。这也将返回 T 的“垂直”条与“水平”条接触的位置。请注意,条件在评估时会短路,并且对具有相同输入数据的函数的重复调用已优化为单次调用。

关于postgresql - 如何找到接触开始/结束节点的 LINESTRING,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30196500/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com