我使用Bing Maps API构建我的javascript应用程序,我想根据中心点和扇区参数来组成扇区几何。
我在PostgreSQL数据库中有一个表“ points”,顶部是PostGIS,它包含点几何:
id st_astext(geom)
1 POINT(4.331 50.869)
2 POINT(4.323 50.832)
3 POINT(4.373 50.853)
4 POINT(4.356 50.837)
和另一个表“ segemnts”,其中每个条目都具有以下属性:方位角(以度为单位),波束宽度(以度为单位),范围(以米为单位)和centerid(基本上是“点”表的外键):
centerid azimuth beamwidth range
1 210 60 750
2 135 30 500
3 80 60 600
4 165 90 750
如何在数据库中获取表格或视图,以选择以上述点为中心,范围为半径,波束宽度为内角,方位角为方向的圆弧段? enter image description here
答案 0 :(得分:2)
您可以使用st_buffer()
来获得围绕点的给定半径的圆,然后使用st_project()
来构建内角等于波束宽度的三角形,然后将其相交以获得扇区几何形状,例如:
create view sectors as
select s1.*, st_intersection(st_buffer(p1.geom::geography, s1.range, 50)::geometry, st_makepolygon(st_makeline(array[p1.geom, st_project(p1.geom::geography, s1.range*2, radians(s1.azimuth-s1.beam/2))::geometry, st_project(p1.geom::geography, s1.range*2, radians(s1.azimuth+s1.beam/2))::geometry, p1.geom]))) as geom
from sector s1
left join points p1
on p1.id=s1.centerid
请注意,我在geography
和geometry
之间使用类型转换来匹配期望的功能参数,而且我将s1.range
乘以了2,所以它足够大,可以切割整个扇区,我使用50作为第三个st_buffer()
参数,因此您的扇区足够平滑。
您的样本数据呈现为某种东西,例如:
答案 1 :(得分:0)
以@ 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;
以弧度为角度旋转二维标题
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