在笔迹中按中心点,半径,内角和方位角绘制扇区

时间:2019-01-24 15:24:44

标签: postgresql gis postgis bing-maps bing-api

我使用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

2 个答案:

答案 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

请注意,我在geographygeometry之间使用类型转换来匹配期望的功能参数,而且我将s1.range乘以了2,所以它足够大,可以切割整个扇区,我使用50作为第三个st_buffer()参数,因此您的扇区足够平滑。

您的样本数据呈现为某种东西,例如:

enter image description here

答案 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