Commit a3e64724 authored by Sandro Santilli's avatar Sandro Santilli

ST_BoundingDiagonal (#3139)

Includes tests and documentation

git-svn-id: http://svn.osgeo.org/postgis/trunk@13599 b70326c6-7e19-0410-871a-916f4a2858ee
parent ccdbd65f
......@@ -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
......
......@@ -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>
......
......@@ -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);
}
......@@ -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
......
......@@ -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
));
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment