]> granicus.if.org Git - postgis/commitdiff
ST_BoundingDiagonal (#3139)
authorSandro Santilli <strk@keybit.net>
Mon, 1 Jun 2015 16:09:22 +0000 (16:09 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 1 Jun 2015 16:09:22 +0000 (16:09 +0000)
Includes tests and documentation

git-svn-id: http://svn.osgeo.org/postgis/trunk@13599 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
doc/reference_accessor.xml
postgis/lwgeom_functions_basic.c
postgis/postgis.sql.in
regress/lwgeom_regress.sql
regress/lwgeom_regress_expected

diff --git a/NEWS b/NEWS
index 765d0d5f92f6b2f514c645e3040e880e98d84ee6..8d6e2de337eee719a124ea3081ca15f016889b2b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,7 @@ PostGIS 2.2.0
 
  * New Features *
 
+  - #3139, ST_BoundingDiagonal (Sandro Santilli / Boundless)
   - #3129, ST_IsValidTrajectory (Sandro Santilli / Boundless)
   - #3128, ST_ClosestPointOfApproach (Sandro Santilli / Boundless)
   - Canonical output for index key types
index dd978193404f9dee0a00806438a5bec62945d609..884b3e613c306297a91dc8e34e203a682e5d5ba3 100644 (file)
@@ -416,6 +416,85 @@ SELECT Box3D(geom), Box2D(geom), ST_AsText(ST_Envelope(geom)) As envelopewkt
          </refsection>
        </refentry>
 
+       <refentry id="ST_BoundingDiagonal">
+                 <refnamediv>
+                       <refname>ST_BoundingDiagonal</refname>
+
+                       <refpurpose>Returns the diagonal of the supplied geometry's bounding box.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>geometry <function>ST_BoundingDiagonal</function></funcdef>
+
+                               <paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
+                               <paramdef choice="opt"><type>boolean </type> <parameter>fits=false</parameter></paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>
+Returns the diagonal of the supplied geometry's bounding box as linestring.
+If the input geometry is empty, the diagonal line is also empty, otherwise
+it is a 2-points linestring with minimum values of each dimension in its
+start point and maximum values in its end point.
+                       </para>
+
+                       <para>
+The returned linestring geometry always retains SRID and dimensionality
+(Z and M presence) of the input geometry.
+                       </para>
+
+                       <para>
+The <varname>fits</varname> parameter specifies if the best fit is needed.
+If false, the diagonal of a somewhat larger bounding box can be accepted
+(is faster to obtain for geometries with a lot of vertices). In any case
+the bounding box of the returned diagonal line always covers the input
+geometry.
+                       </para>
+
+                       <note><para>
+In degenerate cases (a single vertex in input) the returned linestring
+will be topologically invalid (no interior). This does not make the
+return semantically invalid.
+                       </para></note>
+
+                       <para>Availability: 2.2.0</para>
+                       <para>&Z_support;</para>
+                       <para>&M_support;</para>
+               </refsection>
+
+         <refsection>
+               <title>Examples</title>
+
+               <programlisting>
+-- Get the minimum X in a buffer around a point
+SELECT ST_X(ST_StartPoint(ST_BoundingDiagonal(
+  ST_Buffer(ST_MakePoint(0,0),10)
+)));
+ st_x
+------
+  -10
+               </programlisting>
+               </refsection>
+         <refsection>
+               <title>See Also</title>
+               <para>
+<xref linkend="ST_StartPoint" />,
+<xref linkend="ST_EndPoint" />,
+<xref linkend="ST_X" />,
+<xref linkend="ST_Y" />,
+<xref linkend="ST_Z" />,
+<xref linkend="ST_M" />,
+<xref linkend="geometry_overlaps_nd" />
+               </para>
+         </refsection>
+       </refentry>
+
        <refentry id="ST_ExteriorRing">
          <refnamediv>
                <refname>ST_ExteriorRing</refname>
index 6391a9918d99a0588a027a4eda740b56c19f41ad..7b99320ce4cfaa573eb5f4fa152b51c06befa073 100644 (file)
@@ -2744,3 +2744,58 @@ Datum ST_SwapOrdinates(PG_FUNCTION_ARGS)
   PG_FREE_IF_COPY(in, 0);
   PG_RETURN_POINTER(out);
 }
+
+/*
+ * ST_BoundingDiagonal(inp geometry, fits boolean)
+ */
+Datum ST_BoundingDiagonal(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_BoundingDiagonal);
+Datum ST_BoundingDiagonal(PG_FUNCTION_ARGS)
+{
+  GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0);
+  GSERIALIZED *geom_out;
+  bool fits = PG_GETARG_BOOL(1);
+  LWGEOM *lwgeom_in = lwgeom_from_gserialized(geom_in);
+  LWGEOM *lwgeom_out;
+  const GBOX *gbox;
+  int hasz = FLAGS_GET_Z(lwgeom_in->flags);
+  int hasm = FLAGS_GET_M(lwgeom_in->flags);
+  int srid = lwgeom_in->srid;
+  POINT4D pt;
+  POINTARRAY *pa;
+
+  if ( fits ) {
+    /* unregister any cached bbox to ensure it's recomputed */
+    lwgeom_in->bbox = NULL;
+  }
+
+  gbox = lwgeom_get_bbox(lwgeom_in);
+
+  if ( ! gbox )
+  {
+    lwgeom_out = lwgeom_construct_empty(LINETYPE, srid, hasz, hasm);
+  }
+  else
+  {
+    pa = ptarray_construct_empty(hasz, hasm, 2);
+    pt.x = gbox->xmin;
+    pt.y = gbox->ymin;
+    pt.z = gbox->zmin;
+    pt.m = gbox->mmin;
+    ptarray_append_point(pa, &pt, LW_TRUE);
+    pt.x = gbox->xmax;
+    pt.y = gbox->ymax;
+    pt.z = gbox->zmax;
+    pt.m = gbox->mmax;
+    ptarray_append_point(pa, &pt, LW_TRUE);
+    lwgeom_out = lwline_as_lwgeom( lwline_construct(srid, NULL, pa) );
+  }
+
+  lwgeom_free(lwgeom_in);
+  PG_FREE_IF_COPY(geom_in, 0);
+
+  geom_out = geometry_serialize(lwgeom_out);
+  lwgeom_free(lwgeom_out);
+
+  PG_RETURN_POINTER(geom_out);
+}
index f812889aea258b073f1a2645560b33133a0f716d..6171d4b8aa468f8368539fbf6ad1c3c0a9df9f38 100644 (file)
@@ -1478,6 +1478,12 @@ CREATE OR REPLACE FUNCTION ST_Envelope(geometry)
        AS 'MODULE_PATHNAME', 'LWGEOM_envelope'
        LANGUAGE 'c' IMMUTABLE STRICT;
 
+-- Availability: 2.2.0
+CREATE OR REPLACE FUNCTION ST_BoundingDiagonal(geom geometry, fits boolean DEFAULT false)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_BoundingDiagonal'
+       LANGUAGE 'c' IMMUTABLE STRICT;
+
 -- Availability: 1.2.2
 CREATE OR REPLACE FUNCTION ST_Reverse(geometry)
        RETURNS geometry
index d299c8b4c16dc7e7b53c8529ee68ab4c0fa60553..9e4807fd814eba9f27d42af6bccd7ec7de2c453b 100644 (file)
@@ -114,3 +114,24 @@ SELECT '#3069',  postgis_getbbox('SRID=0;LINESTRING(0 0, 1 1)'::geometry);
 SELECT '#3069',  postgis_getbbox('SRID=0;MULTILINESTRING((0 0, 1 1))'::geometry);
 SELECT '#3069',  postgis_getbbox('SRID=0;MULTIPOINT(1 1)'::geometry);
 SELECT '#3069',  postgis_getbbox('SRID=0;MULTILINESTRING((0 0,1 1))'::geometry);
+
+-- ST_BoundingDiagonal
+
+SELECT 'BoundingDiagonal1', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
+    'SRID=4326;POINT(1e+15 1e+15)'::geometry
+)));
+SELECT 'BoundingDiagonal2', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
+    'SRID=4326;POINT(1e+15 1e+15)'::geometry
+), true));
+SELECT 'BoundingDiagonal3', ST_AsEwkt(ST_BoundingDiagonal(postgis_addbbox(
+    'SRID=4326;POINT(1e+15 1e+15)'::geometry
+), false));
+SELECT 'BoundingDiagonal4', ST_AsEwkt(ST_BoundingDiagonal(
+    'SRID=3857;LINESTRING(1 2 3 4, 0 1 -8 2, -1 -2 -3 9)'::geometry
+));
+SELECT 'BoundingDiagonal5', ST_AsEwkt(ST_BoundingDiagonal(
+    'SRID=3857;LINESTRING M (5 4 0,4 4 1)'::geometry
+));
+SELECT 'BoundingDiagonal6', ST_AsEwkt(ST_BoundingDiagonal(
+    'SRID=3857;POLYGON M EMPTY'::geometry
+));
index c4bdcf4afd7d544b13d76eb44e6700d5df50a878..6bc193ed0b995b4c316287b165379d2ef1bd6580 100644 (file)
@@ -15,3 +15,9 @@ BOX3D(0 0.1 -55,11 12 12)
 #3069|BOX(0 0,1 1)
 #3069|BOX(1 1,1 1)
 #3069|BOX(0 0,1 1)
+BoundingDiagonal1|SRID=4326;LINESTRING(999999986991104 999999986991104,999999986991104 999999986991104)
+BoundingDiagonal2|SRID=4326;LINESTRING(1e+15 1e+15,1e+15 1e+15)
+BoundingDiagonal3|SRID=4326;LINESTRING(999999986991104 999999986991104,999999986991104 999999986991104)
+BoundingDiagonal4|SRID=3857;LINESTRING(-1 -2 -8 2,1 2 3 9)
+BoundingDiagonal5|SRID=3857;LINESTRINGM(4 4 0,5 4 1)
+BoundingDiagonal6|SRID=3857;LINESTRINGM EMPTY