如何计算PostGIS中两条线相交的角度?


19

我想计算在PostGIS中相交的两条线之间的角度。

PostGIS中角度计算的起点似乎是ST_Azimuth-但这需要点作为输入。我的第一个想法是采用相交线的端点,并对这些端点执行方位角计算。这还不够好,因为大多数线要素不是笔直的,而且我对相交处的角度感兴趣。所以我想出了一个嵌套的操作,它通过以下步骤进行:

  1. 识别两个线要素表之间的所有交点。
  2. 在相交点周围创建一个非常小的缓冲区
  3. 确定线要素与缓冲区外部相交的点(如果有多个点,则取第一个点-我真的只对角度是接近0、90或180度感兴趣)
  4. 计算这两点的ST_Azimuth。

完整的SQL有点想在这里发布,但是如果您有兴趣的话,我可以在这里进行介绍。(顺便说一句,有没有比继承WITH语句下的所有字段更好的方法了?)

结果看起来不正确,所以我显然做错了:

输出示例1 输出示例2

编辑我在EPSG:3785中重新计算,结果有些不同,但仍然不正确:

在3785#1中输出 在3785#2中输出

我的问题是此过程中的缺陷在哪里。我是否误解了ST_Azimuth的功能?是否存在CRS问题?还有其他东西吗?也许有很多简单的方法可以做到这一点?


1
最初的CRS是什么?角度计算应使用保形投影,而不是未投影的经/纬度(SRID = 4326)。
Mike T

最初是EPSG:4326坐标,我包括ST_Translate只是为了100%确保所有处理都将在同一CRS中完成。我会尝试保形投影,谢谢。
mvexel 2012年

我重新计算的是EPSG:3785,它确实有所作为-我将修改问题以显示新结果-但结果仍未反映实际角度。
mvexel 2012年

Answers:


12

我有顿悟。相当平凡。我为PostGIS遗漏了一些基本信息,以计算直角。

我正在计算的是仅与小缓冲区外部相交的两个点之间的角度。要计算相交的角度,我需要计算缓冲区外部的两个点与两条线要素的相交点之间的两个角度,并将它们相减。

我更新了完整的SQL,但这是要点:

SELECT
    ...
    abs
    (
        round
        (
            degrees
            (
            ST_Azimuth
            (
                points.point2,
                points.intersection
            )
            -
            ST_Azimuth
            (
                points.point1,
                points.intersection
            )
        )::decimal % 180.0
        ,2
    )
)
AS angle
...
FROM
points 

1
我当时在想缓冲与内窥镜之间的角度,但是我没有时间详细介绍。另一方面是角度单位。您需要将ST_Azimuth中的弧度结果乘以180.0 / pi()才能获得度数结果。
Mike T

是的,我为此使用了PostgreSQL degree()函数。
mvexel 2012年

切肉刀 (直到现在我还不知道有一个度数函数。)将所有这些逻辑包装在一个函数调用中会很好,但是我很难概念化它的工作原理,即ST_IntersectionAngle(...
Mike T

实际上,我很惊讶它不是PostGIS功能。感谢您对此的反馈。
mvexel 2012年

2

我最近不得不计算同样的事情,但是决定采用一种更简单,可能更快的方法。

为了找到用于方位角计算的额外点,我只需使用ST_Line_Locate_PointST_Line_Interpolate_Point检查交点后的长度的百分位数(或在极少数情况下发生在直线的开始之后):

abs(degrees( 
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line1, 
      abs(ST_Line_Locate_Point(line1, intersection) - 0.0001)
    )
  )
  -
  ST_Azimuth (
    intersection, 
    ST_Line_Interpolate_Point(
      line2, 
      abs(ST_Line_Locate_Point(line2, intersection) - 0.0001)
    )
  )
))

复数是任意的,为了获得更一致的结果,最好使用绝对偏移。例如,要事先检查20m,则分别将20/ST_Length(line1)和更改为0.0001 20/ST_Length(line2)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.