如何在Postgis中创建一个以米为单位的圆? [英] How to create a circle in meters in postgis?

查看:1099
本文介绍了如何在Postgis中创建一个以米为单位的圆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下如何用radius=4km创建一个圆.我已经尝试过ST_Buffer函数,但是它会创建一个更大的圆圈. (通过将多边形插入新的kml文件中,我看到了所创建的圆圈.)

I would like to ask how to create a circle with radius=4km. I have tried the ST_Buffer function but it creates a larger circle. (I see the created circle by inserting its polygon into an new kml file.)

这就是我正在尝试的.

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

圆的中心是一个点,但是我不知道它的SRID,因为我已经从kml文件中导入了它. 我是否需要SRID才能转换几何形状等?

The center of the circle is a lon lat point but I don't know its SRID because I have imported it from a kml file. Do I need the SRID in order to transform the geometries etc?

推荐答案

KML文件始终为经纬度,并且使用SRID = 4326.如果使用geography,则暗示此SRID.地理是将纬度/经度数据上的4公里度量结合在一起的一种好方法……您尝试过极好!

KML files are always lat/long and use SRID=4326. This SRID is implied if you use geography. Geography is a good way to mix-in the 4 km metric measure on lat/long data ... excellent you tried this!

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

Try this statement to fix up the casts, and use a parameterized point constructor:

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

如果需要将其转换回几何图形,请在末尾添加::geometry转换.

And if you need to cast this back to geometry, add a ::geometry cast to the end.

先前的答案通常在内部将几何图形重新投影到该点适合的UTM区域(请参见方位等距投影.这需要PostGIS 2.3的 ST_Transform ,并且改编自

The previous answer internally re-projects the geometry (usually) to a UTM zone that the point fits within (see ST_Buffer). This may cause minor distortions if the point is on the edge of two UTM boundaries. Most folks won't care about the size of these errors, but it will often be several meters. However, if you require sub millimeter precision, consider building a dynamic azimuthal equidistant projection. This requires PostGIS 2.3's ST_Transform, and is adapted from 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;

运行其中一个功能的简单示例是:

A simple example to run one of the functions is:

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

并比较每个缓冲点的距离,以下是每个大地测量(旋转椭圆体上的最短路径,即WGS84).首先这个功能:

And to compare the distances to each of the buffered points, here are the lengths of each geodesic (shortest path on an ellipsoid of revolution, i.e. WGS84). First this function:

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 m:

Compare this to ST_Buffer (first part of answer), that shows it's off by about 1.56 m:

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

这篇关于如何在Postgis中创建一个以米为单位的圆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆