问题描述
我有一个包含细胞塔信息的数据集,如下所示。纬度和经度字段是塔的位置。
目标是获取信号塔从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,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_angle
和end_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基于相同的概念,它还允许设置每个四分之一圆的最大顶点以及一个可选的内部半径。