创建基站覆盖的区域

问题描述

我有一个包含细胞塔信息的数据集,如下所示。纬度和经度字段是塔的位置。

enter image description here

目标是获取信号塔从start_angle到end_angle所覆盖扇区的面积(几何形状)。如下图所示,以数据集的第一行为例,我可以从start_angle 275和end_angle 35中获取行,但是我希望缓冲区的其余部分消失。

enter image description here

使用的查询

一个查询用于创建和旋转从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,radians(end_angle * -1)),ST_SRID(vertex)) AS endline,radians(0)),ST_SRID(vertex)) AS midline
    
FROM vertices
)

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

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

解决方法

让我们专门为您建立一个方便的inline function on the composite type关系。

首先,让我们为这种情况下的各种用例创建两个同样方便的支持功能;得到两个方位角之间的角度顺时针(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,OUT   ddeg  FLOAT
) LANGUAGE SQL AS
  $$
    SELECT 360.0 - CWAngle(sdeg,edeg);
  $$
;

可能有或没有更有效的方法,或更惯用的代码;效果很好。

现在,以下函数的概念是通过沿给定{沿start_angleend_angle之间的圆弧段投影中心点来创建圆的“楔形”,即圆的扇形。 {1}};我们将投影"radius"个点,因此每个<degrees_between_angles>/FLOOR(<degrees_between_angles>),其中1 <= step < 2(很多; step默认是一个8每四分之一圈的顶点):

ST_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";如果它们实际上不同,则需要相应地更改这些标识符在函数中的所有出现次数

因此,此函数特定于您示例中的关系,您可以像 relationqual列那样调用它:

celulas.lat,celulas.lon,celulas."radius",celulas.start_angle,celulas.end_angle

或者,here is a more general function基于相同的概念,它还允许设置每个四分之一圆的最大顶点以及一个可选的内部半径。