# How to fit a polygon to a “best buffer” about a reference geometry in it?

If I have a polygonal geometry `gbase`, like a street (a rectangular strip), and a reference geometry `gref`, like a central line of `gbase`. The question is what is the function (here named BestBuffer) that returns a geometry `gbest`,

``````gbest = BestBuffer(gbase, gref [,p])
``````

that is the "best fit" for `gbase` and can be generated from `gref` by a ST_Buffer (optionally with a shape parametrized by `p`)?

# Remarks

Formally this is a mathematical optimization problem:

Given: inputs `gref` and `gbase` (optional `p`) and,

``````gbest = ST_Buffer(gref,w,p)
``````

Sought: parameter `w` that supply

``````ST_Area(gbest) = ST_Area(gbase)
``````

NOTE: I think `BestBuffer` can be a "standard library" function (where is it? please show sources/references), not a external plugin, because the estimation checks are all standard OGC build-in functions.

# ILLUSTRATIONS

## BestBuffer when gref is a POINT

Illustrating by the trivial case, the buffer of point, that have exact solution:

is the same as "fit a polygon to a square of equal area" (or a circle).

Inputs: `gbase` a (blue) island, `gref` is only a point, `gref=ST_Centroid(gbase)`, or another position, and the parameter N, that can be 1 for square and 8 for circle.

Results (pink):

``````  gbest_square = bestBuffer(gbase,ST_Centroid(gbase),1);
gbest_circle = bestBuffer(gbase,anotherpoint,8);
``````

You can approximate `gbase` to `gbest` without change original area.

## BestBuffer when gref is a LINE

Illustrating with the Massachusetts avenue,

Inputs: `gbase`, a polygon of a street, `gref` a (blue) center line in it, and the choice of shape (no endcaps)

Result of `gbest=bestBuffer(gbase,gref,'endcap=flat')`

is a rectangle (`gbest`). It is the "best buffer about `gref`" for Massachusetts avenue, filling the same area as `gbase`.

Another cases where you may need to draw BestBuffer of polygons and its central lines: when need to show streets, sidewalks, rivers, etc. with uniform width, instead real/irregular ones.

## BestBuffer when gref is a POLYGON

In the above illustration, the blue polygon represents a island with your beach, as `gbase`, and `gref` the same island without the beach. `gbest0` is the "best buffer" for `gbase`.

Inputs: `gbase` (blue), `gref` a (gray). Can be rendered as `ST_Difference(gbase,gref)`, that represent beachs.

Result: `gbest0=bestBuffer(gbase,gref)`, but we want to render as (`gbest`),

``````  gbest =  ST_Difference(gbest0,gref)
``````

The goal of the buffer of `gref` is to generate the "beach geometry", even if `gbest` not generates an exact `gbase-gref` geometry: it is a good approximation and have uniform width w, the average width of `gbase-gref` (w is mean beach width).

# NOTES

Fit the "best curve" about a set of points in an XY chart is a classical statiscal problem, have classical solutions, and have a lot of tools for it. Similarly the "best curve about another curve" is usual when the "best" is a simple one, like a straight line, a parabola, etc. To fit irregular/complex lines
Cubic spline lines are frequently used.

Where are the standard functions tools for "fit the best polygon in a GIS context"? Are there standard libraries? For generic statistical problems we have external packages that can be integrated with postgreSQL and PostGIS...

But for built-in functions: `ST_Buffer` is a standard function, why not a function `BestBuffer` in a complementary library?

-
Despite the length and detail of this question, I am unable to find a definition or even a clear description of what `BestBuffer` is supposed to do. Could you perhaps give an example? – whuber Sep 25 '12 at 21:11
Thanks, I edited and add figures for better description. – Peter Krauss Sep 26 '12 at 1:52
I still cannot discern a definite problem here. You state, "The goal of the buffer of gref is to generate the beach geometry." Obviously that cannot be done without additional information; for instance, it sounds like you are asking to negatively buffer a polygon and that requires you to stipulate the buffer distance. What, precisely, do you hope the inputs and outputs of your procedure to be? – whuber Sep 26 '12 at 21:13
Ok, editing: now I am illustrating at first paragraphs, inputs and outputs. – Peter Krauss Sep 27 '12 at 0:06
Thank you; it is becoming clearer with your example of Massachusetts Avenue. But in what sense is this rectangle "best"? It's not even a true buffer (the ends are clipped instead of rounded) and it seems likely that the buffer of a slightly nonlinear curve might match the original polygon a little better. – whuber Sep 27 '12 at 0:36

I think if we have a good solution for this other problem (it supplies a `buffer_width` estimation function) we will also have a simple solution here.

## Possible solution when `gref` is a POLYGON

Using the example of the question illustration,

``````wbest  = buffer_width(gbase,gref,p); -- estimation
gbest0 = ST_Buffer(gref,wbest,p);
gbest  = ST_Difference(gbest0,gref);
``````

where to use the optional parameter`p`, you must have a a priory knowledge about the buffer shape/style (like parameters quad_seg, endcap, and join).

## Solution when `gref` is a LINE and `gbase` a strip

There are restrictions for a generalized use, but is stable for strips (shapes near to a "rectangular strip").

``````wbest = buffer_width(gbase,gref,0.0,'endcap=flat'); -- estimation
gbest = ST_Buffer(gref,wbest,'endcap=flat');
``````

See question illustration for details.

## Solution solution when `gref` is a POINT

For this trivial case (buffering a central point) a solution exists (!):

``````gbest = ST_Buffer(ST_Centroid(gbase),buffer_width(gbase,quad_segs),quad_segs)
``````

where the `buffer_width` function is the best average width estimator for point-buffers; and `quad_segs` is a "shape factor" (default is a circle). Below piece of code with a concrete example:

``````SELECT buffer_width(ST_GeomFromText(
'POLYGON((150 90,130 54,100 40,63 53,50 90,40 124,99 140,155 126,150 90))'
),2); -- 53.6
the polygon is a very deformated octagon, but the buffer generates a regular octagon with the same area, by `w=53.6` estimated by the `buffer_width` function.