【问题标题】:How to find LINESTRINGs that touch in a begin/ending node如何找到在开始/结束节点中触及的 LINESTRING
【发布时间】:2015-05-15 10:41:53
【问题描述】:

在 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 个相交的情况。

示例 1:“L”形的两条线在左下角两条线的末端节点相交。

示例 2:“T”形的两条线,其中垂直线与水平线的中间相交。在这种情况下,垂直线末端节点接触到水平线的非末端节点。

示例 3:“X”形的两条线。交点不是任何一条线的终点。

对于我的问题,我只想找到像示例 2 这样的感人场景。

注意

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

geomM, geomN 线串
a、b、c、d、z 点。
(a,b) geomM ST_StartPoint(geom) and 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”形交叉点。

【问题讨论】:

  • 如果“交叉点”位于LINESTRING 的起点或终点节点,而任何中间点位于另一个LINESTRING 上,那么从拓扑上讲,它不是交叉点,而是接触边界。
  • @Patrick 抱歉,但我不熟悉拓扑 lenguaje。我称它为交点,因为我使用ST_Intersect 来查找点。是否有 ST_Touch 返回点?
  • ST_Intersects() 返回一个boolean 来指示两个几何是否相交,ST_Intersection() 返回一个实际相交的geometry。您的问题是“如果交叉点发生在开始/结束节点”;因为该节点是一个geometry(属于POINT),如果它确实触及另一个LINESTRING,它将给出您正在寻找的答案。但这将是一个复杂的WHERE 子句,但是由于您的限制,您可以使用它。

标签: postgresql postgis


【解决方案1】:

您需要 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 基本上只有在您知道线串很短,最好是直线时才可行。

严格的解,只有直线

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

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 的“垂直”条接触“水平”条的位置。请注意,条件在被评估时会短路,并且对具有相同输入数据的函数的重复调用被优化为单个调用。

【讨论】:

  • 感谢您的帮助。不知道触控功能。但不能解决我的问题。我包含了我的部分代码,它只是检查一个开始/结束节点是否等于交点。没有真正密集但很复杂的地方。
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
相关资源
最近更新 更多