Ici, je montre peu d'optimisation à propos de la solution @whuber, et je parle de "largeur de tampon", car cela est utile pour intégrer la solution d'un problème plus général: existe-t-il une fonction inverse de st_buffer, qui renvoie une estimation de la largeur?
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;
Pour ce problème, la question @celenius au sujet de la largeur de la rue , swla solution est
 sw = buffer_width(ST_Length(g1), g2)
où swest la "largeur moyenne", g1la ligne centrale de g2, et la rue g2est un POLYGONE . J'ai utilisé uniquement la bibliothèque standard OGC, testée avec PostGIS , et résolu d'autres applications pratiques sérieuses avec la même fonction buffer_width.
MANIFESTATION
A2est l'aire de g2, L1la longueur de la ligne centrale ( g1) de g2.
Supposons que nous puissions générer g2par g2=ST_Buffer(g1,w), et qu’il g1s’agisse d’une droite, ainsi que d’ g2un rectangle de longueur L1et de largeur 2*w, et
    A2 = L1*(2*w)   -->  w = 0.5*A2/L1
Ce n'est pas la même formule de @whuber, car voici wla moitié de la g2largeur de rectangle ( ). C'est un bon estimateur, mais comme nous pouvons le constater par les tests (ci-dessous), ce n'est pas exact, et la fonction l'utilise comme indice, pour réduire la g2surface, et comme estimateur final.
Ici, nous n'évaluons pas les tampons avec "endcap = square" ou "endcap = round", qui nécessitent la somme   A2  d'une surface d'une mémoire tampon de points avec le même w.
RÉFÉRENCES: dans un forum similaire de 2005 , W. Huber explique des solutions similaires .
TESTS ET RAISONS
Pour les lignes droites, les résultats, comme prévu, sont exacts. Mais pour d'autres géométries, les résultats peuvent être décevants. La raison principale en est que, peut-être, tout le modèle est-il pour des rectangles exacts, ou pour des géométries pouvant être approchées à un "rectangle en bande". Voici un "kit de test" pour vérifier les limites de cette approximation (voir wfactorles résultats ci-dessus).
 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;
RÉSULTATS:
AVEC RECTANGLES (la ligne centrale est une ligne droite): 
         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
AVEC AUTRES GEOMETRIES (ligne centrale pliée):
         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.
À propos, btypevoir le guide ST_Buffer , avec les bons ilustratins et les LINESTRING utilisés ici.
CONCLUSIONS :
- l'estimateur de w_estimest toujours meilleur quew_near;
- pour les g2géométries "presque rectangulaires" , c'est ok, toutwfactor
- pour les autres géométries (proches des "bandes rectangulaires"), utilisez la limite wfactor=~0.01de 1% d'erreur surw_estim. Jusqu'à ce facteur, utilisez un autre estimateur.
Attention et prévention
Pourquoi l'erreur d'estimation se produit? Lorsque vous utilisez ST_Buffer(g,w), prévu, par le « modèle de bande rectangulaire », que la nouvelle zone ajoutée par le tampon de la largeur west d' environ w*ST_Length(g)ou w*ST_Perimeter(g)... Lorsqu'ils ne sont pas, en général par des superpositions (voir les lignes pliées) ou en « coiffant », est quand l'estimation de la wfaute moyenne . C'est le message principal des tests.
Pour détecter ce problème à n’importe quel roi de tampon , vérifiez le comportement de la génération de tampon:
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;
RÉSULTATS:
         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%
        