如何在postgis中创建一个以米为单位的圆圈?

问题描述 投票:6回答:1

我想问一下如何用radius=4km创建一个圆圈。我尝试了ST_Buffer功能,但它创建了一个更大的圆圈。 (我通过将其多边形插入到新的kml文件中来查看创建的圆圈。)

这就是我想要的。

INSERT INTO camera(geom_circle) VALUES(geometry(ST_Buffer(georgaphy(ST_GeomFromText('POINT(21.304116745663165 38.68607570952619)')), 4000)))

圆的中心是一个lon lat点,但我不知道它的SRID因为我从kml文件导入它。我是否需要SRID来改变几何形状等?

postgis geometry srid
1个回答
18
投票

KML文件始终为纬度/经度,并使用SRID = 4326。如果您使用geography,则隐含此SRID。地理位置是一种很好的方法,可以在纬度/经度数据上混合使用4公里的度量标准...非常棒的你试过这个!

尝试使用此语句来修复强制转换,并使用参数化的点构造函数:

SELECT ST_Buffer(ST_MakePoint(21.304116745663165, 38.68607570952619)::geography, 4000);

如果您需要将其强制转换为几何体,请在最后添加一个::geometry


Update on accuracy

前面的答案在内部将几何体(通常)重新投影到该点所适合的UTM区域(参见ST_Buffer)。如果该点位于两个UTM边界的边缘,则可能导致轻微失真。大多数人不会关心这些错误的大小,但通常会有几米。但是,如果您需要亚毫米精度,请考虑构建动态azimuthal equidistant projection。这需要PostGIS 2.3的ST_Transform,并改编自another answer

CREATE OR REPLACE FUNCTION geodesic_buffer(geom geometry, dist double precision,
                                           num_seg_quarter_circle integer)
  RETURNS geometry AS $$
  SELECT ST_Transform(
    ST_Buffer(ST_Point(0, 0), $2, $3),
      ('+proj=aeqd +x_0=0 +y_0=0 +lat_0='
       || ST_Y(ST_Centroid($1))::text || ' +lon_0=' || ST_X(ST_Centroid($1))::text),
      ST_SRID($1))
  $$ LANGUAGE sql IMMUTABLE STRICT COST 100;
CREATE OR REPLACE FUNCTION geodesic_buffer(geom geometry, dist double precision)
  RETURNS geometry AS 'SELECT geodesic_buffer($1, $2, 8)'
  LANGUAGE sql IMMUTABLE STRICT COST 100;
-- Optional warppers for geography type
CREATE OR REPLACE FUNCTION geodesic_buffer(geog geography, dist double precision)
  RETURNS geography AS 'SELECT geodesic_buffer($1::geometry, $2)::geography'
LANGUAGE sql IMMUTABLE STRICT COST 100;
CREATE OR REPLACE FUNCTION geodesic_buffer(geog geography, dist double precision,
                                           num_seg_quarter_circle integer)
  RETURNS geography AS 'SELECT geodesic_buffer($1::geometry, $2, $3)::geography'
  LANGUAGE sql IMMUTABLE STRICT COST 100;

运行其中一个函数的一个简单示例是:

SELECT geodesic_buffer(ST_MakePoint(21.304116745663165, 38.68607570952619)::geography, 4000);

并且为了比较每个缓冲点的距离,这里是每个geodesic的长度(旋转椭圆体上的最短路径,即WGS84)。首先这个功能:

SELECT count(*), min(buff_dist), avg(buff_dist), max(buff_dist)
FROM (
  SELECT ST_Distance((ST_DumpPoints(geodesic_buffer(poi, dist)::geometry)).geom, poi) AS buff_dist
  FROM (SELECT ST_MakePoint(21.304116745663165, 38.68607570952619)::geography AS poi, 4000 AS dist) AS f
) AS f;

 count |      min       |       avg       |      max
-------+----------------+-----------------+----------------
    33 | 3999.999999953 | 3999.9999999743 | 4000.000000001

将此与ST_Buffer(答案的第一部分)进行比较,显示它关闭了大约1.56米:

SELECT count(*), min(buff_dist), avg(buff_dist), max(buff_dist)
FROM (
  SELECT ST_Distance((ST_DumpPoints(ST_Buffer(poi, dist)::geometry)).geom, poi) AS buff_dist
  FROM (SELECT ST_MakePoint(21.304116745663165, 38.68607570952619)::geography AS poi, 4000 AS dist) AS f
) AS f;

 count |      min       |       avg        |      max
-------+----------------+------------------+----------------
    33 | 4001.560675049 | 4001.56585986067 | 4001.571105793
© www.soinside.com 2019 - 2024. All rights reserved.