名前

ST_Buffer — あるジオメトリからの距離が指定された距離以下となる点全ての集合となるジオメトリを返します。

概要

geometry ST_Buffer(geometry g1, float radius_of_buffer, text buffer_style_parameters = '');

geometry ST_Buffer(geometry g1, float radius_of_buffer, integer num_seg_quarter_circle);

geography ST_Buffer(geography g1, float radius_of_buffer, text buffer_style_parameters);

geography ST_Buffer(geography g1, float radius_of_buffer, integer num_seg_quarter_circle);

説明

ジオメトリ/ジオグラフィからの距離が与えられた距離より短くなる全ての点を表現するPOLYGONまたはMULTIPOLYGONを生成します。距離に負数を指定すると、ジオメトリは拡大されずに縮小されます。負の距離ではポリゴンを完全に縮小し切る可能性があり、その時はPOLYGON EMPTYを返します。ポイントとラインで負の距離を指定すると、常に空を返します。

ジオメトリの場合、指定される距離の単位は、ジオメトリの空間参照系の単位です。ジオグラフィの場合、指定される距離の単位はメートルです。

3番目のパラメータは任意で、バッファの精度とスタイルを扱います。バッファの円弧の精度は四分の一円の近似に使用される辺の数です (デフォルトは8)。バッファのスタイルは キー=値 のペアを空白区切りでリストにして指定します。キーは次の通りです。

  • 'quad_segs=#' : 四分の一円近似に使う辺の数 (デフォルトは8)。

  • 'endcap=round|flat|square' : 終端スタイル (デフォルトは "round")。'butt'は'flat'の同義語として受け付けます。

  • 'join=round|mitre|bevel' : 接続スタイル (デフォルトは"round")。'miter'も'mitre'の同義語として受け付けます。

  • 'mitre_limit=#.#' : マイター比 (訳注: 継ぎ目の内側と外側の距離と線幅との比)の最大値 (継ぎ目スタイルがmiterである場合のみ有効)。'miter_limit'は'mitre_limit'の同義語として受け付けます。

  • 'side=both|left|right' : デフォルトは'both'です。'left'または'right'でジオメトリーの片側へのバッファーが行われますが、左右はラインの方向で決まります。これはLINESTRINGジオメトリーにのみ適用可能です。POINTまたはPOLYGONジオメトリに影響を与えません。'left'または'right'を指定した場合にはデフォルトの終端スタイルは正方形になります。

[注記]

この関数のジオグラフィー版はジオメトリ実装にかぶせた薄いラッパーです。 ジオメトリのバウンディングボックスに最適な平面空間参照系を決定します (UTM、ランベルト正積方位図法の北極/南極、最後はメルカトルです)。バッファは平面空間で計算あsれ、WGS84に戻されます。このため、入力がUTMゾーンと比べて非常に大きくなったり、日付変更線とクロスしたりする場合に、求める動作をしないことがあります

[注記]

不正な入力を操作することができ、出力は常に妥当なポリゴンジオメトリです。距離 0によるバッファ生成は時々不正なポリゴンの修復方法として使われます。. ST_MakeValidの方がマルチポリゴンも扱えるので、この目的に使うのにより適切です。

[注記]

バッファ作成は時々、距離内にある地物を検索する際に使われます。この使い方については、ST_DWithinの方が効率的です。

[注記]

この関数はZ値を無視します。この関数を3次元ジオメトリ上で使用したとしても、常に2次元の結果となります。

Enhanced: 2.5.0 - ST_Bufferのジオメトリ対応版が強化され、バッファを施す側をside=both|left|rightで指定できるようになりました。

Availability: 1.5 - ST_Bufferが強化され、様々な終端と継ぎ目に対応するようになりました。たとえば、道路ラインストリングを道路ポリゴンに変換する際に終端を丸でなく平面や四角で処理したい場合などに使えます。ジオグラフィ用の薄いラッパが追加されました。

GEOSモジュールで実現しています。

このメソッドはOGC Simple Features Implementation Specification for SQL 1.1の実装です。 s2.1.1.3

このメソッドはSQL/MM仕様の実装です。 SQL-MM IEC 13249-3: 5.1.30

文字の結果は読みやすくするために全体の整数に丸められています。結果は文字としても出ていますが、マニュアルは最初は入出力の共有された図の方がいいと思います。

quad_segs=8 (デフォルト)

Code
SELECT ST_Buffer(
  ST_GeomFromText('POINT(100 90)'),
  50, 'quad_segs=8');
出力:
POLYGON((150 90,149 80,146 71,142 62,135 55,128 48,119 44,110 41,100 40,90 41,81 44,72 48,65 55,58 62,54 71,51 80,50 90,51 100,54 109,58 118,65 125,72 132,81 136,90 139,100 140,110 139,119 136,128 132,135 125,142 118,146 109,149 100,150 90))
Figure
Geometry figure for st-buffer-example-01

quad_segs=2

Code
SELECT ST_Buffer(
  ST_GeomFromText('POINT(100 90)'),
  50, 'quad_segs=2');
出力:
POLYGON((150 90,135 55,100 40,65 55,50 90,65 125,100 140,135 125,150 90))
Figure
Geometry figure for st-buffer-example-02

endcap=round join=round (デフォルト)

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'endcap=round join=round');
出力:
POLYGON((143 157,144 158,146 159,148 160,150 160,152 160,154 159,156 158,157 157,158 156,159 154,160 152,160 150,160 50,160 48,159 46,158 44,157 43,156 42,154 41,152 40,150 40,148 40,146 41,144 42,143 43,142 44,141 46,140 48,140 50,140 126,57 43,56 42,54 41,52 40,50 40,48 40,46 41,44 42,43 43,42 44,41 46,40 48,40 50,40 52,41 54,42 56,43 57,143 157))
Figure
Geometry figure for st-buffer-example-03

endcap=square

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'endcap=square join=round');
出力:
POLYGON((143 157,144 158,146 159,148 160,150 160,152 160,154 159,156 158,157 157,158 156,159 154,160 152,160 150,160 50,160 40,140 40,140 126,57 43,50 36,36 50,143 157))
Figure
Geometry figure for st-buffer-example-04

endcap=flat

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'endcap=flat join=round');
出力:
POLYGON((143 157,144 158,146 159,148 160,150 160,152 160,154 159,156 158,157 157,158 156,159 154,160 152,160 150,160 50,140 50,140 126,57 43,43 57,143 157))
Figure
Geometry figure for st-buffer-example-05

join=bevel

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'join=bevel');
出力:
POLYGON((143 157,160 150,160 50,160 48,159 46,158 44,157 43,156 42,154 41,152 40,150 40,148 40,146 41,144 42,143 43,142 44,141 46,140 48,140 50,140 126,57 43,56 42,54 41,52 40,50 40,48 40,46 41,44 42,43 43,42 44,41 46,40 48,40 50,40 52,41 54,42 56,43 57,143 157))
Figure
Geometry figure for st-buffer-example-06

join=mitre mitre_limit=5.0 (デフォルトの最大マイター比)

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'join=mitre mitre_limit=5.0');
出力:
POLYGON((160 174,160 50,160 48,159 46,158 44,157 43,156 42,154 41,152 40,150 40,148 40,146 41,144 42,143 43,142 44,141 46,140 48,140 50,140 126,57 43,56 42,54 41,52 40,50 40,48 40,46 41,44 42,43 43,42 44,41 46,40 48,40 50,40 52,41 54,42 56,43 57,160 174))
Figure
Geometry figure for st-buffer-example-07

join=mitre mitre_limit=1

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'join=mitre mitre_limit=1.0');
出力:
POLYGON((148 162,160 157,160 50,160 48,159 46,158 44,157 43,156 42,154 41,152 40,150 40,148 40,146 41,144 42,143 43,142 44,141 46,140 48,140 50,140 126,57 43,56 42,54 41,52 40,50 40,48 40,46 41,44 42,43 43,42 44,41 46,40 48,40 50,40 52,41 54,42 56,43 57,148 162))
Figure
Geometry figure for st-buffer-example-08

side=left

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'side=left');
出力:
POLYGON((150 50,150 150,50 50,43 57,143 157,144 158,146 159,148 160,150 160,152 160,154 159,156 158,157 157,158 156,159 154,160 152,160 150,160 50,150 50))
Figure
Geometry figure for st-buffer-example-09

side=right

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'side=right');
出力:
POLYGON((50 50,150 150,150 50,140 50,140 126,57 43,50 50))
Figure
Geometry figure for st-buffer-example-10

side=left join=mitre

Code
SELECT ST_Buffer(
  ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'),
  10, 'side=left join=mitre');
出力:
POLYGON((150 50,150 150,50 50,43 57,160 174,160 50,150 50))
Figure
Geometry figure for st-buffer-example-11

右回りに強制し、ポリゴンの境界に対して side=left

Code
SELECT ST_Buffer(
  ST_ForceRHR(ST_Boundary(ST_GeomFromText(
    'POLYGON ((50 50,50 150,150 150,150 50,50 50))'))),
  20, 'side=left');
出力:
POLYGON((50 50,50 150,150 150,150 50,50 50))
Figure
Geometry figure for st-buffer-example-12

右回りに強制し、ポリゴン境界に対して site=right

Code
SELECT ST_Buffer(
  ST_ForceRHR(ST_Boundary(ST_GeomFromText(
    'POLYGON ((50 50,50 150,150 150,150 50,50 50))'))),
  20, 'side=right');
出力:
POLYGON((50 50,50 70,50 150,150 150,150 50,70 50,50 50),(70 70,130 70,130 130,70 130,70 70))
Figure
Geometry figure for st-buffer-example-13
 

バッファーを施したポイントは近似円になります。ポイントに四分円ごとに二つのポイント (図を参照)の近似を行うようバッファーを施した場合には8辺のポリゴンになります (図を参照)。

Code
SELECT ST_NPoints(ST_Buffer('POINT(100 90)'::geometry, 50)) As promisingcircle_pcount,
ST_NPoints(ST_Buffer('POINT(100 90)'::geometry, 50, 2)) As lamecircle_pcount;
出力:
promisingcircle_pcount | lamecircle_pcount
------------------------+-------------------
             33 |                9

四分円に2ポイントだけ使うようにすると、より軽くなるけど円が角張って八角形になります。

次の例では NAD83 緯度/経度からメートル単位マサチューセッツ州平面に投影変換してからバッファーを生成する手順で 100m 八角形を生成します。下図では、入力と出力は別 SRID になっているので別パネルで表示しています。

Code
WITH input AS (
  SELECT ST_SetSRID(ST_Point(-71.063526, 42.35785), 4269) AS point_4269
), projected AS (
  SELECT point_4269,
         ST_Transform(point_4269, 26986) AS point_26986
  FROM input
)
SELECT point_4269 AS input_point_4269,
       ST_Buffer(point_26986, 100, 2) AS octagon_26986
FROM projected;
出力:
SRID=4269;POINT(-71.063526 42.35785) | SRID=26986;POLYGON((236057.5905746494 900908.7599186979,236028.30125276805 900838.0492405792,235957.5905746494 900808.7599186979,235886.87989653074 900838.0492405792,235857.5905746494 900908.7599186979,235886.87989653074 900979.4705968165,235957.5905746494 901008.7599186979,236028.30125276805 900979.4705968165,236057.5905746494 900908.7599186979))
Figure
Geometry figure for visual-st-buffer-15

ポリゴンに対して正の距離でバッファーを施し、同じだけ負の距離でバッファーを施すのは、数学的形態学ではクロージング処理と言います。海岸線の狭い入江を除くことで行う簡略化など、ノイズが多い境界線を平滑化するのに使います。結果は、入力の形状や面積が変化しますが、指定する距離は入力 SRS の単位で選択しなければなりません。ジオグラフィーの SRS のデータは、最初に処理に適した投影座標系の SRS に変換します。Web メルカトルで地図表示をする場合には、表示 SRS を使うといいです。

1km クロージング処理を使って海岸線を平滑化します。この例ではメートル単位マサチューセッツ州平面を使います。

Code
WITH projected AS (
  SELECT id, ST_Transform(geom, 26986) AS geom
  FROM coast
),
closed AS (
  SELECT id, ST_Buffer(ST_Buffer(geom, 1000), -1000) AS geom
  FROM projected
)
SELECT id, ST_Transform(ST_SimplifyPreserveTopology(geom, 50), 4326) AS geom
FROM closed;

同じ技術は Paul Ramsey さんの Removing Complexities に記述があります。単純化の最後の手順は任意です。ポリゴン妥当性評価が問題となる時には ST_SimplifyPreserveTopology を使い、結果に対してアプリケーションが求める地図表示または分析に関する許容範囲に対する確認をします。

小さい負数は狭いポリゴンの突起を探す時に経験則的に使われます。下のクエリーは収縮後の面積と周囲長の大きさを比較します。大きな erosion_index は、この値に比例して、面積よりも多く周囲長が減っていることを示しています。

Code
WITH sample(id, geom) AS (
  VALUES
    ('plain', 'POLYGON((0 0,10 0,10 10,0 10,0 0))'::geometry),
    ('spike', 'POLYGON((0 0,10 0,10 10,5.2 10,5 16,4.8 10,0 10,0 0))'::geometry)
),
eroded AS (
  SELECT id, geom, ST_Buffer(geom, -0.5) AS eroded_geom
  FROM sample
),
scored AS (
  SELECT id,
         round((
           ST_Area(eroded_geom) / ST_Area(geom) /
           NULLIF(ST_Perimeter(eroded_geom) / ST_Perimeter(geom), 0)
         )::numeric, 3) AS erosion_index
  FROM eroded
  WHERE NOT ST_IsEmpty(eroded_geom)
)
SELECT id, erosion_index, erosion_index > 1.1 AS possible_spike
FROM scored
ORDER BY id;
出力:
id   | erosion_index | possible_spike
-------+---------------+----------------
 plain |         0.900 | f
 spike |         1.147 | t
Figure
Geometry figure for visual-st-buffer-16

可変距離バッファーはラインに沿った補間点のバッファーを生成し、バッファーの連続する二個組の凸包を構築し、辺の凸包を結合することで近似できます。いずれのジオメトリーバッファーであっても距離の単位は入力 SRS の単位です。

ラインのバッファーの先をラインに沿って 5単位から 25単位に細くします。

Code
WITH line AS (
  SELECT 'LINESTRING(0 0, 100 0, 160 40)'::geometry AS geom
),
vertices AS (
  SELECT (dump).path[1] AS n,
         (dump).geom AS geom,
         line.geom AS line_geom
  FROM line
  CROSS JOIN LATERAL ST_DumpPoints(line.geom) AS dump
),
radii AS (
  SELECT n,
         geom,
         5 + (25 - 5) * ST_LineLocatePoint(line_geom, geom) AS radius
  FROM vertices
),
segments AS (
  SELECT n,
         geom,
         radius,
         lead(geom) OVER (ORDER BY n) AS next_geom,
         lead(radius) OVER (ORDER BY n) AS next_radius
  FROM radii
)
SELECT ST_Union(
         ST_ConvexHull(
           ST_Collect(
             ST_Buffer(geom, radius),
             ST_Buffer(next_geom, next_radius)
           )
         )
       ) AS tapered_buffer
FROM segments
WHERE next_geom IS NOT NULL;
出力:
POLYGON((96.758 -16.301,-0.975 -4.904,-1.913 -4.619,-2.778 -4.157,-3.536 -3.536,-4.157 -2.778,-4.619 -1.913,-4.904 -0.975,-5 0,-4.904 0.975,-4.619 1.913,-4.157 2.778,-3.536 3.536,-2.778 4.157,-1.913 4.619,-0.975 4.904,93.101 15.875,142.322 57.678,146.111 60.787,150.433 63.097,155.123 64.52,160 65,164.877 64.52,169.567 63.097,173.889 60.787,177.678 57.678,180.787 53.889,183.097 49.567,184.52 44.877,185 40,184.52 35.123,183.097 30.433,180.787 26.111,177.678 22.322,173.889 19.213,169.567 16.903,106.36 -15.355,103.242 -16.301,100 -16.62,96.758 -16.301))
Figure
Geometry figure for visual-st-buffer-17