Thursday 26 September 2019

spatial statistics - 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)?



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:


enter image description here


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,


    the Massachusetts avenue


gbase and gref


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')


gbest


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


enter image description here


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?



Answer



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.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...