Di sini saya menunjukkan sedikit optimasi tentang solusi @whuber, dan saya memasukkan istilah "lebar buffer", karena ini berguna untuk mengintegrasikan solusi dari masalah yang lebih umum: Apakah ada fungsi invers st_buffer, yang mengembalikan estimasi lebar?
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;
Untuk masalah ini, pertanyaan @celenius tentang lebar jalan , sw
, solusinya adalah
sw = buffer_width(ST_Length(g1), g2)
di mana sw
"lebar rata-rata", g1
garis tengah g2
, dan jalan g2
adalah POLYGON . Saya hanya menggunakan pustaka standar OGC, diuji dengan PostGIS , dan menyelesaikan aplikasi praktis serius lainnya dengan fungsi buffer_width yang sama.
DEMONSTRASI
A2
adalah luas g2
, L1
panjang garis tengah ( g1
) dari g2
.
Misalkan kita dapat menghasilkan g2
dengan g2=ST_Buffer(g1,w)
, dan itu g1
adalah lurus, jadi g2
adalah persegi panjang dengan panjang L1
dan lebar 2*w
, dan
A2 = L1*(2*w) --> w = 0.5*A2/L1
Ini bukan formula yang sama dengan @whuber, karena w
ini adalah setengah dari g2
lebar persegi panjang ( ). Ini adalah penduga yang baik, tetapi seperti yang dapat kita lihat dengan tes (di bawah), tidak tepat, dan fungsinya menggunakannya sebagai petunjuk, untuk mengurangi g2
area, dan sebagai penduga akhir.
Di sini kita tidak mengevaluasi buffer dengan "endcap = square" atau "endcap = round", yang membutuhkan penjumlahan A2
dari area buffer titik dengan yang sama w
.
DAFTAR PUSTAKA: dalam forum serupa tahun 2005 , W. Huber menjelaskan solusi sejenis dan lainnya.
UJI DAN ALASAN
Untuk garis lurus hasilnya, seperti yang diharapkan, tepat. Tetapi untuk geometri lainnya hasilnya bisa mengecewakan. Alasan utamanya adalah, mungkin, semua model adalah untuk persegi panjang yang tepat, atau untuk geometri yang dapat diperkirakan menjadi "strip persegi panjang". Di sini "test kit" untuk memeriksa batas perkiraan ini (lihat wfactor
hasil di atas).
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;
HASIL:
DENGAN RECTANGLES (jalur sentral adalah LURUS LURUS):
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
DENGAN GEOMETRI LAINNYA (garis tengah dilipat):
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.
Tentang btype
lihat panduan ST_Buffer , dengan ilustratin yang baik dan LINESTRING yang digunakan di sini.
KESIMPULAN :
- penaksir
w_estim
selalu lebih baik daripada w_near
;
- untuk
g2
geometri "dekat ke persegi panjang" , ok, apa sajawfactor
- untuk geometri lain (dekat dengan "strip segi empat"), gunakan batas
wfactor=~0.01
untuk kesalahan 1% w_estim
. Sampai di wfactor ini, gunakan estimator lain.
Perhatian dan pencegahan
Mengapa kesalahan estimasi terjadi? Ketika Anda menggunakan ST_Buffer(g,w)
, Anda harapkan, dengan "model strip persegi panjang", bahwa area baru yang ditambahkan oleh buffer lebar w
sekitar w*ST_Length(g)
atau w*ST_Perimeter(g)
... Ketika tidak, biasanya dengan overlay (lihat garis terlipat) atau dengan "gaya", adalah ketika estimasi w
kesalahan rata-rata . Ini adalah pesan utama dari tes ini.
Untuk mendeteksi masalah ini di sembarang raja buffer , periksa perilaku generasi buffer:
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;
HASIL:
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%