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
)?
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.
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).
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?
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 parameterp
, 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
SELECT ST_Area(ST_Buffer(ST_GeomFromText('POINT(100 90)'),53.6,'quad_segs=2'));
-- 8126
SELECT ST_Area(ST_GeomFromText(
'POLYGON((150 90,130 54,100 40,63 53,50 90,40 124,99 140,155 126,150 90))')
); -- 8126
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.