如何查找在开始/结束节点中触摸的LINESTRING

时间:2015-05-12 16:23:11

标签: postgresql postgis

在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 Linestring
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"形状交叉点。

1 个答案:

答案 0 :(得分:2)

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