[postgis-tickets] [PostGIS] #3176: Add ST_MinimumRectangle

PostGIS trac at osgeo.org
Wed Jul 1 12:37:37 PDT 2015


#3176: Add ST_MinimumRectangle
--------------------------+----------------------------
  Reporter:  mwtoews      |      Owner:  pramsey
      Type:  enhancement  |     Status:  new
  Priority:  medium       |  Milestone:  PostGIS Future
 Component:  postgis      |    Version:  2.1.x
Resolution:               |   Keywords:
--------------------------+----------------------------

Comment (by nw):

 I think the following works.  I think but haven't proved that a side of a
 minimum rectangle must contain one of the sides of the convex hull of the
 point geometries.  So this algorithm iterates through those sides and
 rotates
 the hull to be parallel to the y axis, calculates a bounding box, and
 counter
 rotates it.  This gives a number of candidate rectangles, from which I
 choose
 the smallest, then the "first" based on the sides counting out from the
 first
 point in the case of ties.

 This is just to make the algorithm stable.  There
 isn't in general a unique minimum rectangle (think of a hexagon).  There
 could
 be other choice mechanisms, since the rectangle chosen (potentially)
 depends on
 the ordering of the points.  The rectangle could alternatively be chosen
 based on
 the angle of the major side of the rectangle to the X axis, which I think
 is
 then independent of the point ordering.

 This also doesn't handle degenerate rectangles.  If the approach seem
 sound, once
 a rectangle choice method is chosen, I will implement that and take care
 of the degenerate cases.

 {{{
 create or replace function ST_MinimumRectangle(g geometry) returns
 geometry
 language 'plpgsql' as $$
 declare
         hull geometry;
 begin
         hull = ST_ExteriorRing(ST_ConvexHull(g));
         -- one side must lie along the rectangle.
         -- so, for each side, rotate, bbox, counter-rotate bbox
         with sides as (
                 select ST_PointN(hull, n) as a, ST_PointN(hull, n+1) as b,
                         n as side
                         from generate_series(1,ST_NPoints(hull)-1) n
                 ),
         angles as (
                 select side, a, b, st_azimuth(a, b) as angle from sides
         ),
         boxes as (
                 select ST_Rotate(ST_Envelope(ST_Rotate(hull,
 -angle)),angle) as rect, side, angle from angles
         )
         select rect into hull from boxes order by ST_Area(rect), side
 limit 1
         ;
         return hull;
 end;
 $$ immutable strict;
 }}}

--
Ticket URL: <https://trac.osgeo.org/postgis/ticket/3176#comment:1>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.


More information about the postgis-tickets mailing list