以@user3307073 的答案为基础,并将其扩展到处理大于或等于 180 度的角度。
首先是一些辅助函数:
将弧度角归一化为 (-pi,pi)
create or replace function misc_normalizeRadians(rad double precision)
returns double precision
as $$
SELECT r-floor(r/pi())*(2*pi()) FROM (SELECT (floor($1/(2*pi()))*-(2*pi())+$1) as r) as t;
$$ LANGUAGE sql immutable;
以弧度为单位旋转 2D 航向
create or replace function misc_rotateHeadingByAngle(heading double precision,angle double precision)
returns double precision
as $$
select misc_normalizeRadians($1-$2);
$$ LANGUAGE sql immutable;
构建一个三角形,指定原点、方向、内角和边长
create or replace function util_buildCone(origin geometry,bearing double precision,angle double precision,sides double precision)
returns geometry
as $$
BEGIN
IF ST_GeometryType($1)!='ST_Point' THEN
RAISE EXCEPTION 'Function only well defined for points, got: %',ST_GeometryType($1);
END IF;
IF abs($3)>=pi() THEN
RAISE EXCEPTION 'Cones can''t have interior angle greater or equal to half a rotation, got: %',$3;
END IF;
RETURN (select ST_MakePolygon(ST_MakeLine(ARRAY[$1,a,b,$1]))
from
util_translateTowardsBearing($1,misc_rotateHeadingByAngle($2,$3/2),$4) as a,
util_translateTowardsBearing($1,misc_rotateHeadingByAngle($2,-$3/2),$4) as b);
END
$$ language plpgsql immutable;
根据原点、航向、内角和半径构建一个圆形扇区
create or replace function buildSector(origin geometry,bearing double precision,angle double precision,sides double precision)
returns geometry
as $$
BEGIN
IF ST_GeometryType($1)!='ST_Point' THEN
RAISE EXCEPTION 'Function only well defined for points, got: %',ST_GeometryType($1);
END IF;
IF abs($3)>(2*pi()) THEN
RAISE EXCEPTION 'Cones can''t have a sector greater than the whole circle, got : %',$3;
END IF;
IF abs($3)=(2*pi()) THEN
RETURN (select ST_Buffer($1,$4,50));
END IF;
IF abs($3)>(pi()/2) THEN
RETURN (select ST_Union(a,ST_Snap(b,a,$4/10000))
from buildSector($1,misc_rotateHeadingByAngle($2,$3/4),$3/2,$4) as a,
buildSector($1,misc_rotateHeadingByAngle($2,-$3/4),$3/2,$4) as b);
END IF;
RETURN (select ST_Intersection(ST_Buffer($1,$4,50),util_buildCone($1,$2,$3,$4*2)));
END
$$ language plpgsql immutable;
然后创建视图:
create view sectors as
select s1.*, buildSector(p1.geom,s1.azimuth,s1.beam,s1.range) as geom
from sector s1 left join points p1 on p1.id=s1.centerid