在这里,我没有显示有关@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。我仅使用经过PostGIS测试的OGC标准库,并使用相同的buffer_width函数解决了其他严重的实际应用。
示范
A2
是的面积g2
,L1
是的中心线(g1
)的长度g2
。
假设我们可以生成g2
的g2=ST_Buffer(g1,w)
,这g1
是直的,所以g2
是lenght长方形L1
和宽度2*w
,以及
A2 = L1*(2*w) --> w = 0.5*A2/L1
@whuber的公式不同,因为这w
是矩形(g2
)宽度的一半。这是一个很好的估计器,但是正如我们在测试中看到的(如下)所示,它并不精确,该函数将其用作线索,减小g2
面积并作为最终估计器。
在这里,我们不评估“ endcap = square”或“ endcap = round”的缓冲区,它们需要 A2
与之相同的点缓冲区的面积之和w
。
参考文献:在2005年的类似论坛上,W。Huber解释了此类解决方案和其他解决方案。
测试和理由
对于直线,结果如预期的那样准确。但是对于其他几何形状,结果可能令人失望。主要原因可能是,所有模型都是针对精确的矩形,或者是近似于“条形矩形”的几何。这里是一个“测试套件”,用于检查该近似值的极限(请参见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指南,其中包含良好的ilustratins和LINESTRING。
结论:
- 的估计
w_estim
总是优于w_near
;
- 对于“接近矩形”的
g2
几何形状,可以wfactor
- 对于其他几何形状(“矩形条”附近),请使用的
wfactor=~0.01
1%误差极限w_estim
。在此之前,请使用另一个估算器。
注意和预防
为什么会出现估计误差?当使用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%