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'を指定した場合にはデフォルトの終端スタイルは正方形になります。
|
|
|
|
|
|
|
不正な入力を操作することができ、出力は常に妥当なポリゴンジオメトリです。距離 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
The textual results are rounded to whole coordinate units for readability. Each result remains available as text, while the manual initially favors the shared input/output figure.
|
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 |
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 |
|
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 |
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 |
|
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 |
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 |
|
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 |
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 |
|
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 |
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 |
|
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 |
right-hand winding, polygon boundary 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 |
|
right-hand winding, polygon boundary side=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 |
バッファーを施したポイントは近似円になります。ポイントに四分円ごとに二つのポイント (図を参照)の近似を行うようバッファーを施した場合には8辺のポリゴンになります (図を参照)。
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ポイントだけ使うようにすると、より軽くなるけど円が角張って八角形になります。
The following example creates a 100 meter octagon in NAD83 longitude/latitude by transforming to the Massachusetts state plane meter projection and then buffering. The figure shows the input and output in separate panels because the coordinates are in different SRIDs.
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))
Buffering a polygon by a positive distance and then by the same negative distance is a morphological closing operation. It can be useful for smoothing noisy boundaries, such as simplifying a coastline by removing narrow inlets and bays. The result intentionally changes the shape and area of the input, and the distance must be chosen in the units of the input SRS. For data in a geographic SRS, transform to a projected SRS suited to the operation first; for cartographic visualization in Web Mercator, using that display SRS can be appropriate.
Smooth a coastline using a 1 km closing operation, then simplify the result. The example uses Massachusetts State Plane meter units for the operation.
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;
The same technique is described in Paul Ramsey's Removing Complexities. The final simplification step is optional; use ST_SimplifyPreserveTopology when polygonal validity matters, and check the result against the cartographic or analytical tolerance required by the application.
A small negative buffer can also be used as a heuristic to find narrow polygon spikes. The query below compares how much area and perimeter remain after erosion. A large erosion_index indicates that the perimeter dropped proportionally more than the area. This is only a preselection aid; the threshold and buffer distance must be chosen for the data units and the kind of spike being checked.
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
A variable-distance buffer can be approximated by buffering each vertex of a line by a distance interpolated along the line, building the convex hull for each consecutive pair of vertex buffers, and unioning the segment hulls. As with any geometry buffer, distances are in the units of the input SRS.
Taper a line buffer from 5 to 25 units along the line.
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))