PostGIS에 저장되어있는 Polygon에 대해 가장 긴 변의 길이를 구하고 싶다는 요청이 들어왔다. 

이에 구글링하면서 레퍼런스를 찾았고 그 결과에 대해 좀 더 덧붙여서 기록하려고 한다. 

 

원본

레퍼런스 : https://stackoverflow.com/questions/7595635/how-to-convert-polygon-data-into-line-segments-using-postgis

 

SELECT ST_AsText( ST_MakeLine(sp,ep) )
FROM
   -- extract the endpoints for every 2-point line segment for each linestring
   -- call two points as start point and end point from each boundary(linestring)
   (SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep
    FROM
       -- extract the individual linestrings
       -- ST_Dump : multi-part to single-parts ex) Multipolygon to a set of polygons
      (SELECT (ST_Dump(ST_Boundary(geom))).geom
       FROM mypolygontable
       ) AS linestrings
    ) AS segments;
  • ST_Dump : 한 feature를 이루고 있는 하위 단계의 feature들이 존재한다면 ST_Dump는 이를 하위 단계의 feature들의 집합으로 변환해서 내보낸다. multipolygon의 경우 여러 polygon들이 모여서 multipolygon을 이루기 때문에 ST_Dump(multipolygon)의 결과는 polygon의 집합이다. 
  • generate_series : generate_series(start, stop, step) 
  • ST_PointN : N번째 점을 얻는 함수. 

2개의 view가 사용되어 좀 정신없을 수 있는데 차근 차근 보면 view의 결과를 엮을 수 있을 것이다. 

 

예시코드

SELECT ST_length( ST_MakeLine(sp,ep) )
FROM
   -- extract the endpoints for every 2-point line segment for each linestring
   (SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep
    FROM
       -- extract the individual linestrings
      (SELECT (ST_Dump(ST_Transform(ST_Boundary(ST_Polygon('LINESTRING(75 29, 77 29, 77 25, 75 25, 75 29)'::geometry, 4326)), 3857))).geom

       ) AS linestrings
    ) AS segments;

결과

222638.98158654384
499901.41056706756
222638.98158654384
499901.41056706756

ST_length는 대상의 좌표계의 unit에 따라 길이를 계산하기 때문에, meter로 계산하려면 3857로 transform해줘야 한다. 

+ Recent posts