在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
注意,我在geography
和geometry
之间使用类型转换来匹配预期的函数参数,我也乘以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
我正在使用 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
注意,我在geography
和geometry
之间使用类型转换来匹配预期的函数参数,我也乘以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