在postgis中按中心点、半径、内角和方位角绘制扇区

Draw sector by center point, radius, interior angle and azymuth in postgis

我正在使用 Bing 地图 API 构建一个 javascript 应用程序,我想根据中心点和扇形参数构成扇形几何图形。

我在 PostgreSQL 数据库中有一个 table '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)

我有另一个 table 'segemnts' 其中每个条目都有以下属性:方位角(以度为单位)、波束宽度(以度为单位)、范围(以米为单位)和基本上是外键的 centerid 'points' table:

centerid    azimuth beamwidth   range
1           210     60          750
2           135     30          500
3           80      60          600
4           165     90          750

如何在我的数据库中获取 table 或 select 圆段的视图,这些圆段以上述点为中心点,范围为半径,波束宽度为内角,方位角为方向?

您可以使用 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两个,所以它足以切割整个扇区,我使用 50 作为第三个 st_buffer() 参数,所以你的扇区足够平滑。

您的示例数据呈现为某些内容,例如:

基于@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(/(2*pi()))*-(2*pi())+) 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(-);
$$ 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()!='ST_Point' THEN
         RAISE EXCEPTION 'Function only well defined for points, got: %',ST_GeometryType();
    END IF;
    IF abs()>=pi() THEN
         RAISE EXCEPTION 'Cones can''t have interior angle greater or equal to half a rotation, got: %',;
    END IF;
    RETURN (select ST_MakePolygon(ST_MakeLine(ARRAY[,a,b,]))
            from
                 util_translateTowardsBearing(,misc_rotateHeadingByAngle(,/2),) as a,
                 util_translateTowardsBearing(,misc_rotateHeadingByAngle(,-/2),) 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()!='ST_Point' THEN
        RAISE EXCEPTION 'Function only well defined for points, got: %',ST_GeometryType();
    END IF;
    IF abs()>(2*pi()) THEN
        RAISE EXCEPTION 'Cones can''t have a sector greater than the whole circle, got : %',;
    END IF;
    IF abs()=(2*pi()) THEN
        RETURN (select ST_Buffer(,,50));
    END IF;
    IF abs()>(pi()/2) THEN
        RETURN (select  ST_Union(a,ST_Snap(b,a,/10000))
                from    buildSector(,misc_rotateHeadingByAngle(,/4),/2,) as a,
                        buildSector(,misc_rotateHeadingByAngle(,-/4),/2,) as b);
    END IF;
    RETURN (select ST_Intersection(ST_Buffer(,,50),util_buildCone(,,,*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