2

我有一个包含手机信号塔信息的数据集,如下所示。lat 和 lon 字段是塔的位置。

在此处输入图像描述

目标是获取蜂窝塔覆盖的扇区的面积(几何形状),从 start_angle 到 end_angle。正如您在下一张图片中看到的那样,以数据集的第一行为例,我可以从 start_angle 275 和 end_angle 35 获取行,但我希望缓冲区的其余部分消失。

在此处输入图像描述

使用的查询:

第一个查询用于创建和旋转 start_angle 和 end_angle 的线以及 0 度的线。

WITH vertices AS
(SELECT 
      id,
 start_angle,
 end_angle,
      (ST_DumpPoints(geom)).path[1] AS v_id, 
      (ST_DumpPoints(geom)).geom AS vertex
FROM celulas
), teste as
(SELECT
    id,
    v_id,
    ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 1.0,0.0), 
                                                  ST_MakePoint(-1.0,0.0)),
                                      radians(start_angle * -1)), ST_X(vertex), ST_Y(Vertex)),
                                      ST_SRID(vertex)) AS startline,
    ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 1.0,0.0), 
                                                  ST_MakePoint(-1.0,0.0)),
                                      radians(end_angle * -1)), ST_X(vertex), ST_Y(Vertex)),
                                      ST_SRID(vertex)) AS endline,
    ST_SetSRID(ST_Translate(ST_Rotate(ST_MakeLine(ST_MakePoint( 1.0,0.0), 
                                                  ST_MakePoint(-1.0,0.0)),
                                      radians(0)), ST_X(vertex), ST_Y(Vertex)),
                                      ST_SRID(vertex)) AS midline
    
FROM vertices
)

我还使用下一个查询来合并所有几何图形:半径缓冲区和线条

select St_intersection(st_split(buffer, midline), st_split(buffer, angulo))
from angulo
4

1 回答 1

1

让我们专门为您的关系的复合类型创建一个方便的内联函数。

另外,首先,让我们为这种上下文中的各种用例创建两个同样方便的支持函数;获得两个方位角之间的顺时针 (CW)(并且,因为我们在它,也是逆时针 (CW))角度差异:

CREATE OR REPLACE FUNCTION CWAngle(
  IN    sdeg FLOAT,
  IN    edeg FLOAT,
  OUT   ddeg  FLOAT
) LANGUAGE SQL AS
  $$
    SELECT CASE (sdeg <= edeg)
             WHEN TRUE THEN
               edeg - sdeg
             ELSE
               360.0 - sdeg + edeg
           END;
  $$
;

CREATE OR REPLACE FUNCTION CCWAngle(
  IN    sdeg FLOAT,
  IN    edeg FLOAT,
  OUT   ddeg  FLOAT
) LANGUAGE SQL AS
  $$
    SELECT 360.0 - CWAngle(sdeg, edeg);
  $$
;

可能有也可能没有更有效的方法,或者更惯用的代码;这工作得很好。

现在,以下函数的概念是通过将中心点沿圆弧投影在给定之间start_angle和处来创建圆的“楔形”,即您的扇区;我们将投影点,所以每个,都带有度数(很多;默认为每四分之一圆有 8 个顶点的圆):end_angle"radius"<degrees_between_angles>/FLOOR(<degrees_between_angles>)1 <= step < 2stepST_Buffer

CREATE OR REPLACE FUNCTION sector(
    rec spatial.celulas
) RETURNS GEOMETRY(POLYGON, 4236) AS
  $$
    DECLARE
      delta FLOAT := CWAngle(rec.start_angle, rec.end_angle);
      step  FLOAT := delta / FLOOR(delta);
      
      wedge GEOMETRY(POINT)[];
      
    BEGIN
      wedge := wedge || ST_SetSRID(ST_MakePoint(rec.lon, rec.lat), 4326);
  
      FOR n IN 0..FLOOR(delta)
        LOOP
          wedge := wedge || ST_Project(wedge[1]::GEOGRAPHY, rec."radius", RADIANS(MOD(rec.start_angle+(n*step)::NUMERIC, 360.0::NUMERIC)))::GEOMETRY;
        END LOOP
      ;
  
      wedge := wedge || wedge[1];
      
      RETURN ST_MakePolygon(ST_SetSRID(ST_MakeLine(wedge), 4326));
    END;
  $$
LANGUAGE 'plpgsql';

这假设

  • CWAngle功能存在;CCWAngle如果需要,在此函数中更改
  • start_angle->end_angle顺时针方向
  • "radius"为单位
  • 您的示例的确切关系和列名,即celulas.lat, celulas.lon, celulas."radius", celulas.start_angle, celulas.end_angle;如果它们实际上不同,则需要相应地更改函数中这些标识符的所有出现

因此,此函数特定于您示例中的关系,您可以将其称为关系限定列

SELECT [*,] celulas.sector AS geom
FROM   celulas
;

或者,这里有一个基于相同概念的更通用的函数,它还允许设置每四分之一圆的最大顶点数和可选的内半径。

于 2020-09-25T11:56:20.250 回答