PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ST_TileEnvelope()

Datum ST_TileEnvelope ( PG_FUNCTION_ARGS  )

Definition at line 2091 of file lwgeom_functions_basic.c.

2092{
2093 GSERIALIZED *bounds;
2094 uint32_t zoomu;
2095 int32_t x, y, zoom;
2096 uint32_t worldTileSize;
2097 double tileGeoSizeX, tileGeoSizeY;
2098 double boundsWidth, boundsHeight;
2099 double x1, y1, x2, y2;
2100 double margin;
2101 /* This is broken, since 3857 doesn't mean "web mercator", it means
2102 the contents of the row in spatial_ref_sys with srid = 3857.
2103 For practical purposes this will work, but in good implementation
2104 we should de-reference in spatial ref sys to confirm that the
2105 srid of the object is EPSG:3857. */
2106 int32_t srid;
2107 GBOX bbox;
2108 LWGEOM *g = NULL;
2109
2110 POSTGIS_DEBUG(2, "ST_TileEnvelope called");
2111
2112 zoom = PG_GETARG_INT32(0);
2113 x = PG_GETARG_INT32(1);
2114 y = PG_GETARG_INT32(2);
2115
2116 bounds = PG_GETARG_GSERIALIZED_P(3);
2117 /*
2118 * We deserialize the geometry and recalculate the bounding box here to get
2119 * 64b floating point precision. The serialized bbox has 32b float is not
2120 * precise enough with big numbers such as the ones used in the default
2121 * parameters, e.g: -20037508.3427892 is transformed into -20037510
2122 */
2123 g = lwgeom_from_gserialized(bounds);
2124 if (lwgeom_calculate_gbox(g, &bbox) != LW_SUCCESS)
2125 elog(ERROR, "%s: Unable to compute bbox", __func__);
2126 srid = g->srid;
2127 lwgeom_free(g);
2128
2129 /* Avoid crashing with old signature (old sql code with 3 args, new C code with 4) */
2130 margin = PG_NARGS() < 4 ? 0 : PG_GETARG_FLOAT8(4);
2131 /* shrinking by more than 50% would eliminate the tile outright */
2132 if (margin < -0.5)
2133 elog(ERROR, "%s: Margin must not be less than -50%%, margin=%f", __func__, margin);
2134
2135 boundsWidth = bbox.xmax - bbox.xmin;
2136 boundsHeight = bbox.ymax - bbox.ymin;
2137 if (boundsWidth <= 0 || boundsHeight <= 0)
2138 elog(ERROR, "%s: Geometric bounds are too small", __func__);
2139
2140 if (zoom < 0 || zoom >= 32)
2141 elog(ERROR, "%s: Invalid tile zoom value, %d", __func__, zoom);
2142
2143 zoomu = (uint32_t)zoom;
2144 worldTileSize = 0x01u << (zoomu > 31 ? 31 : zoomu);
2145
2146 if (x < 0 || (uint32_t)x >= worldTileSize)
2147 elog(ERROR, "%s: Invalid tile x value, %d", __func__, x);
2148 if (y < 0 || (uint32_t)y >= worldTileSize)
2149 elog(ERROR, "%s: Invalid tile y value, %d", __func__, y);
2150
2151 tileGeoSizeX = boundsWidth / worldTileSize;
2152 tileGeoSizeY = boundsHeight / worldTileSize;
2153
2154 /*
2155 * 1 margin (100%) is the same as a single tile width
2156 * if the size of the tile with margins span more than the total number of tiles,
2157 * reset x1/x2 to the bounds
2158 */
2159 if ((1 + margin * 2) > worldTileSize)
2160 {
2161 x1 = bbox.xmin;
2162 x2 = bbox.xmax;
2163 }
2164 else
2165 {
2166 x1 = bbox.xmin + tileGeoSizeX * (x - margin);
2167 x2 = bbox.xmin + tileGeoSizeX * (x + 1 + margin);
2168 }
2169
2170 y1 = bbox.ymax - tileGeoSizeY * (y + 1 + margin);
2171 y2 = bbox.ymax - tileGeoSizeY * (y - margin);
2172
2173 /* Clip the final tile bounds to the bounds of the tile plane */
2174 if (y1 < bbox.ymin) y1 = bbox.ymin;
2175 if (y2 > bbox.ymax) y2 = bbox.ymax;
2176 if (x1 < bbox.xmin) x1 = bbox.xmin;
2177 if (x2 > bbox.xmax) x2 = bbox.xmax;
2178
2179 PG_RETURN_POINTER(
2180 geometry_serialize(
2183 srid, x1, y1, x2, y2))));
2184}
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define LW_SUCCESS
Definition liblwgeom.h:97
LWPOLY * lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2)
Definition lwpoly.c:98
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition lwgeom.c:783
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
double ymax
Definition liblwgeom.h:357
double xmax
Definition liblwgeom.h:355
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
int32_t srid
Definition liblwgeom.h:460

References LW_SUCCESS, lwgeom_calculate_gbox(), lwgeom_free(), lwgeom_from_gserialized(), lwpoly_as_lwgeom(), lwpoly_construct_envelope(), LWGEOM::srid, GBOX::xmax, GBOX::xmin, GBOX::ymax, and GBOX::ymin.

Here is the call graph for this function: