ここでは、@ whuberソリューションについてほとんど最適化を示していませんが、より一般的な問題のソリューションを統合するのに役立つため、「バッファー幅」の観点から説明しています。幅推定を返すst_buffer逆関数はありますか?
CREATE FUNCTION buffer_width(
-- rectangular strip mean width estimator
p_len float, -- len of the central line of g
p_geom geometry, -- g
p_btype varchar DEFAULT 'endcap=flat' -- st_buffer() parameter
) RETURNS float AS $f$
DECLARE
w_half float;
w float;
BEGIN
w_half := 0.25*ST_Area(p_geom)/p_len;
w := 0.50*ST_Area( ST_Buffer(p_geom,-w_half,p_btype) )/(p_len-2.0*w_half);
RETURN w_half+w;
END
$f$ LANGUAGE plpgsql IMMUTABLE;
この問題のために、およそ@celenius質問ストリート幅は、sw
、解決策はあります
sw = buffer_width(ST_Length(g1), g2)
ここsw
で、「平均幅」、g1
の中心線g2
、および通りg2
はPOLYGONです。OGC標準ライブラリのみを使用し、PostGISでテストし、同じbuffer_width関数で他の深刻な実用的なアプリケーションを解決しました。
デモンストレーション
A2
領域でありg2
、L1
(中心線の長さg1
)のg2
。
我々が生成できると仮定g2
することによりg2=ST_Buffer(g1,w)
、それがg1
ストレートなので、g2
な長さを持つ長方形でL1
、幅は2*w
、と
A2 = L1*(2*w) --> w = 0.5*A2/L1
これは、@ whuberと同じ式ではありません。これはw
、長方形(g2
)幅の半分だからです。これは適切な推定量ですが、テスト(下記)でわかるように正確ではありません。関数はそれを手掛かりとして使用し、g2
面積を減らし、最終的な推定量として使用します。
ここでは、「endcap = square」または「endcap = round」のバッファを評価しません。これらA2
は同じのポイントバッファの面積の合計を必要 としw
ます。
参考資料:2005年の同様のフォーラムで、W。フーバーはそのようなソリューションやその他のソリューションについて説明しています。
テストと理由
直線の場合、予想どおり、結果は正確です。しかし、他のジオメトリの場合、結果はがっかりする可能性があります。主な理由は、おそらく、すべてのモデルが正確な長方形、または「ストリップ長方形」に近似できるジオメトリのためです。ここに、この近似の限界をチェックするための「テストキット」があります(wfactor
上記の結果を参照)。
SELECT *, round(100.0*(w_estim-w)/w,1) as estim_perc_error
FROM (
SELECT btype, round(len,1) AS len, w, round(w/len,3) AS wfactor,
round( buffer_width(len, gbase, btype) ,2) as w_estim ,
round( 0.5*ST_Area(gbase)/len ,2) as w_near
FROM (
SELECT
*, st_length(g) AS len, ST_Buffer(g, w, btype) AS gbase
FROM (
-- SELECT ST_GeomFromText('LINESTRING(50 50,150 150)') AS g, -- straight
SELECT ST_GeomFromText('LINESTRING(50 50,150 150,150 50,250 250)') AS g,
unnest(array[1.0,10.0,20.0,50.0]) AS w
) AS t,
(SELECT unnest(array['endcap=flat','endcap=flat join=bevel']) AS btype
) AS t2
) as t3
) as t4;
結果:
長方形あり(中心線は直線です):
btype | len | w | wfactor | w_estim | w_near | estim_perc_error
------------------------+-------+------+---------+---------+--------+------------------
endcap=flat | 141.4 | 1.0 | 0.007 | 1 | 1 | 0
endcap=flat join=bevel | 141.4 | 1.0 | 0.007 | 1 | 1 | 0
endcap=flat | 141.4 | 10.0 | 0.071 | 10 | 10 | 0
endcap=flat join=bevel | 141.4 | 10.0 | 0.071 | 10 | 10 | 0
endcap=flat | 141.4 | 20.0 | 0.141 | 20 | 20 | 0
endcap=flat join=bevel | 141.4 | 20.0 | 0.141 | 20 | 20 | 0
endcap=flat | 141.4 | 50.0 | 0.354 | 50 | 50 | 0
endcap=flat join=bevel | 141.4 | 50.0 | 0.354 | 50 | 50 | 0
その他のジオメトリー(折り畳まれた中心線):
btype | len | w | wfactor | w_estim | w_near | estim_perc_error
-----------------------+-----+------+---------+---------+--------+------------------
endcap=flat | 465 | 1.0 | 0.002 | 1 | 1 | 0
endcap=flat join=bevel | 465 | 1.0 | 0.002 | 1 | 0.99 | 0
endcap=flat | 465 | 10.0 | 0.022 | 9.98 | 9.55 | -0.2
endcap=flat join=bevel | 465 | 10.0 | 0.022 | 9.88 | 9.35 | -1.2
endcap=flat | 465 | 20.0 | 0.043 | 19.83 | 18.22 | -0.9
endcap=flat join=bevel | 465 | 20.0 | 0.043 | 19.33 | 17.39 | -3.4
endcap=flat | 465 | 50.0 | 0.108 | 46.29 | 40.47 | -7.4
endcap=flat join=bevel | 465 | 50.0 | 0.108 | 41.76 | 36.65 | -16.5
wfactor= w/len
w_near = 0.5*area/len
w_estim is the proposed estimator, the buffer_width function.
についてbtype
は、ST_Bufferガイドをご覧ください。ここには、優れたイルストラチンとLINESTRINGが使用されています。
結論:
- の推定量
w_estim
は常に以下よりも優れていw_near
ます。
- 「長方形に近い」
g2
ジオメトリの場合は、OKwfactor
- 別のジオメトリ(「長方形のストリップ」に近い)の場合、
wfactor=~0.01
エラーの1%の制限を使用しw_estim
ます。このwfactorまでは、別の推定量を使用します。
注意と予防
推定エラーが発生する理由 を使用する場合ST_Buffer(g,w)
、「長方形ストリップモデル」によって、幅のバッファによって追加される新しい領域w
は約w*ST_Length(g)
またはw*ST_Perimeter(g)
... であると予想されます。そうでない場合、通常はオーバーレイ(折り線を参照)または「スタイリング」によって、平均w
断層の推定。これがテストのメインメッセージです。
バッファキングでこの問題を検出するには、バッファ生成の動作を確認します。
SELECT btype, w, round(100.0*(a1-len1*2.0*w)/a1)::varchar||'%' AS straight_error,
round(100.0*(a2-len2*2.0*w)/a2)::varchar||'%' AS curve2_error,
round(100.0*(a3-len3*2.0*w)/a3)::varchar||'%' AS curve3_error
FROM (
SELECT
*, st_length(g1) AS len1, ST_Area(ST_Buffer(g1, w, btype)) AS a1,
st_length(g2) AS len2, ST_Area(ST_Buffer(g2, w, btype)) AS a2,
st_length(g3) AS len3, ST_Area(ST_Buffer(g3, w, btype)) AS a3
FROM (
SELECT ST_GeomFromText('LINESTRING(50 50,150 150)') AS g1, -- straight
ST_GeomFromText('LINESTRING(50 50,150 150,150 50)') AS g2,
ST_GeomFromText('LINESTRING(50 50,150 150,150 50,250 250)') AS g3,
unnest(array[1.0,20.0,50.0]) AS w
) AS t,
(SELECT unnest(array['endcap=flat','endcap=flat join=bevel']) AS btype
) AS t2
) as t3;
結果:
btype | w | straight_error | curve2_error | curve3_error
------------------------+------+----------------+--------------+--------------
endcap=flat | 1.0 | 0% | -0% | -0%
endcap=flat join=bevel | 1.0 | 0% | -0% | -1%
endcap=flat | 20.0 | 0% | -5% | -10%
endcap=flat join=bevel | 20.0 | 0% | -9% | -15%
endcap=flat | 50.0 | 0% | -14% | -24%
endcap=flat join=bevel | 50.0 | 0% | -26% | -36%