【问题标题】:Draw sector by center point, radius, interior angle and azymuth in postgis在postgis中按中心点、半径、内角和方位角绘制扇区
【发布时间】:2019-06-18 09:18:04
【问题描述】:

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

如何在我的数据库中获取表格或视图来选择以以上点为中心点、范围为半径、波束宽度为内角、方位角为方向的圆段?

【问题讨论】:

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


    【解决方案1】:

    您可以使用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() 参数,因此您的扇区足够平滑。

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

    【讨论】:

    • 对我来说,这样的解释听起来对于 180 度或更大的内角会失败
    【解决方案2】:

    以@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
    

    【讨论】:

      猜你喜欢
      • 2016-07-26
      • 2021-08-30
      • 1970-01-01
      • 2022-07-22
      • 2023-01-21
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多