여기에 @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
A는 다각형 . PostGIS로 테스트 한 OGC 표준 라이브러리 만 사용 했으며 동일한 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
w
사각형 ( g2
) 너비 의 절반 이므로 @whuber와 같은 공식이 아닙니다 . 그것은 좋은 추정기이지만, 우리가 테스트 (아래)에서 볼 수 있듯이 정확하지 않으며 함수는 그것을 단서로 사용하여 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;
결과 :
WITH RECTANGLES (중앙선은 직선)입니다.
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 여기에 사용되는 선 스트링으로.
결론 :
- 추정기
w_estim
는 항상보다 낫다 w_near
.
- "직사각형 근처"
g2
지오메트리의 경우wfactor
- 다른 형상 ( "직사각형 스트립"근처)의 경우
wfactor=~0.01
에 1 %의 오차 한계 를 사용하십시오 w_estim
. 이 wfactor까지 다른 추정기를 사용하십시오.
주의 및 예방
추정 오차가 발생하는 이유는 무엇입니까? 당신이 사용하는 경우 ST_Buffer(g,w)
, 당신은 폭 버퍼에 의해 추가 된 새로운 영역이 있음은 "직사각형 스트립 모델"으로 기대 w
에 관한 w*ST_Length(g)
또는 w*ST_Perimeter(g)
... 보통 오버레이 (접힌 선 참조) 또는으로 "스타일링"하지 않을 때, 때이다 평균 w
결함 추정 . 이것이 테스트의 주요 메시지입니다.
모든 king of 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;
결과 :
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%