Ở đây tôi chỉ ra một chút tối ưu hóa về giải pháp @whuber và tôi đang đặt vấn đề về "độ rộng bộ đệm", bởi vì nó rất hữu ích để tích hợp giải pháp cho một vấn đề tổng quát hơn: Có hàm nghịch đảo st_buffer, trả về ước tính độ rộng không?
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;
Đối với vấn đề này, câu hỏi @celenius về chiều rộng đường , sw
, giải pháp là
sw = buffer_width(ST_Length(g1), g2)
trong đó sw
"chiều rộng trung bình", g1
đường trung tâm g2
và đường phố g2
là POLYGON . Tôi chỉ sử dụng thư viện tiêu chuẩn OGC, được thử nghiệm với PostGIS và giải quyết các ứng dụng thực tế nghiêm trọng khác có cùng chức năng đệm.
MÔ PHỎNG
A2
là diện tích của g2
, L1
độ dài của đường trung tâm ( g1
) của g2
.
Giả sử rằng chúng ta có thể tạo g2
bởi g2=ST_Buffer(g1,w)
và đó g1
là một đường thẳng, g2
hình chữ nhật có chiều dài L1
và chiều rộng 2*w
, và
A2 = L1*(2*w) --> w = 0.5*A2/L1
Nó không phải là cùng một công thức của @whuber, bởi vì đây w
là một nửa g2
chiều rộng hình chữ nhật ( ). Nó là một công cụ ước tính tốt, nhưng như chúng ta có thể thấy bằng các thử nghiệm (bên dưới), không chính xác và hàm sử dụng nó như một đầu mối, để giảm g2
diện tích và làm công cụ ước tính cuối cùng.
Ở đây chúng tôi không đánh giá bộ đệm với "endcap = vuông" hoặc "endcap = round", cần tổng A2
của một khu vực của bộ đệm điểm giống nhau w
.
TÀI LIỆU THAM KHẢO: trong một diễn đàn tương tự năm 2005 , W. Huber giải thích những giải pháp tương tự và khác.
KIỂM TRA VÀ LÝ DO
Đối với các đường thẳng, kết quả, như mong đợi, là chính xác. Nhưng đối với hình học khác, kết quả có thể gây thất vọng. Lý do chính là, có lẽ, tất cả các mô hình là cho hình chữ nhật chính xác, hoặc cho hình học có thể xấp xỉ với một "hình chữ nhật dải". Ở đây một "bộ kiểm tra" để kiểm tra các giới hạn của phép tính gần đúng này (xem wfactor
trong các kết quả ở trên).
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;
CÁC KẾT QUẢ:
VỚI RECTANGLES (đường trung tâm là LINE STRAIGHT):
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
VỚI GEOMETRIES KHÁC (đường trung tâm gấp):
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.
Giới thiệu btype
xem hướng dẫn ST_Buffer , với ilustratin tốt và LINESTRING được sử dụng ở đây.
KẾT LUẬN :
- công cụ ước tính
w_estim
luôn luôn tốt hơn w_near
;
- cho
g2
hình học "gần hình chữ nhật" , ok, bất kỳwfactor
- đối với hình học khác (gần "dải hình chữ nhật"), sử dụng giới hạn
wfactor=~0.01
cho 1% lỗi trên w_estim
. Lên đến wfactor này, sử dụng một công cụ ước tính khác.
Thận trọng và phòng ngừa
Tại sao xảy ra lỗi ước tính? Khi bạn sử dụng ST_Buffer(g,w)
, bạn mong đợi, theo "mô hình dải hình chữ nhật", rằng khu vực mới được thêm bởi bộ đệm có chiều rộng w
khoảng w*ST_Length(g)
hoặc w*ST_Perimeter(g)
... Khi không, thường là bởi các lớp phủ (xem các đường gấp) hoặc "kiểu dáng", là khi ước tính w
sai số trung bình . Đây là thông điệp chính của các bài kiểm tra.
Để phát hiện vấn đề này tại bất kỳ vị vua đệm nào , hãy kiểm tra hành vi của việc tạo bộ đệm:
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;
CÁC KẾT QUẢ:
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%