Hier zeige ich nur eine geringe Optimierung der @ whuber-Lösung und gebe die "Pufferbreite" an, da dies nützlich ist, um die Lösung eines allgemeineren Problems zu integrieren: Gibt es eine st_buffer-Umkehrfunktion, die eine Breitenschätzung zurückgibt?
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;
Für dieses Problem der @celenius Frage nach Breiter Straße , sw
ist die Lösung
sw = buffer_width(ST_Length(g1), g2)
wo sw
ist die "durchschnittliche Breite", g1
die Mittellinie von g2
und die Straße g2
ist ein POLYGON . Ich habe nur die mit PostGIS getestete OGC-Standardbibliothek verwendet und andere ernsthafte praktische Anwendungen mit derselben buffer_width-Funktion gelöst.
DEMONSTRATION
A2
ist die Fläche von g2
, L1
die Länge der Mittellinie ( g1
) von g2
.
Angenommen , dass wir erzeugen kann g2
durch g2=ST_Buffer(g1,w)
, und das g1
ist eine gerade, so g2
ist ein Rechteck mit Länge L1
und Breite 2*w
, und
A2 = L1*(2*w) --> w = 0.5*A2/L1
Es ist nicht die gleiche Formel von @whuber, da hier die w
Hälfte der g2
Breite von rectangle ( ) angegeben ist. Es ist ein guter Schätzer, aber wie wir anhand der Tests (unten) sehen können, ist er nicht genau und die Funktion verwendet ihn als Anhaltspunkt, um die g2
Fläche zu verkleinern und als endgültigen Schätzer.
Hier werden keine Puffer mit "endcap = square" oder "endcap = round" ausgewertet, die eine Summe zu A2
einer Fläche eines Punktpuffers mit derselben benötigen w
.
LITERATUR: In einem ähnlichen Forum von 2005 erklärt W. Huber ähnliche und andere Lösungen.
PRÜFUNGEN UND GRÜNDE
Bei geraden Linien sind die Ergebnisse erwartungsgemäß genau. Bei anderen Geometrien können die Ergebnisse jedoch enttäuschend sein. Der Hauptgrund ist möglicherweise, dass das gesamte Modell für exakte Rechtecke oder für Geometrien bestimmt ist, die sich einem "Streifenrechteck" annähern lassen. Hier ein "Testkit" zur Überprüfung der Grenzen dieser Näherung (siehe wfactor
Ergebnisse oben).
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;
ERGEBNISSE:
MIT RECHTECKEN (Mittellinie ist eine GERADE LINIE):
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
MIT ANDEREN GEOMETRIEN (Mittellinie gefaltet):
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.
Über btype
siehe ST_Buffer Führung , mit guten ilustratins und den Linienfolgen verwendet hier.
SCHLUSSFOLGERUNGEN :
- der Schätzer von
w_estim
ist immer besser als w_near
;
- Für "fast rechteckige"
g2
Geometrien ist es in Ordnungwfactor
- Verwenden Sie für andere Geometrien (in der Nähe von "rechteckigen Streifen") die Grenze
wfactor=~0.01
für 1% des Fehlers auf w_estim
. Verwenden Sie bis zu diesem Faktor einen anderen Schätzer.
Vorsicht und Vorbeugung
Warum tritt der Schätzfehler auf? Wenn Sie verwenden ST_Buffer(g,w)
, erwarten Sie vom "rechteckigen Streifenmodell", dass der neue Bereich, der durch den Puffer mit der Breite hinzugefügt w
wird, ungefähr w*ST_Length(g)
oder w*ST_Perimeter(g)
... Wenn nicht, normalerweise durch Überlagerungen (siehe gefaltete Linien) oder durch "Stylen", wann die Schätzung des durchschnittlichen w
Fehlers . Dies ist die Hauptbotschaft der Tests.
Überprüfen Sie das Verhalten der Puffergenerierung , um dieses Problem bei jedem Pufferkönig zu erkennen :
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;
ERGEBNISSE:
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%