* 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
</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>
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);
+}
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
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
+));
#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