return geom_out;
}
+static LWGEOM *
+mvt_clip_and_validate_geos(LWGEOM *lwgeom, uint8_t basic_type, uint32_t extent, uint32_t buffer, bool clip_geom)
+{
+ LWGEOM *ng = lwgeom;
+
+ if (clip_geom)
+ {
+ GBOX bgbox, lwgeom_gbox;
+ gbox_init(&bgbox);
+ gbox_init(&lwgeom_gbox);
+ bgbox.xmax = bgbox.ymax = (double)extent + (double)buffer;
+ bgbox.xmin = bgbox.ymin = -(double)buffer;
+ FLAGS_SET_GEODETIC(lwgeom_gbox.flags, 0);
+ FLAGS_SET_GEODETIC(bgbox.flags, 0);
+ lwgeom_calculate_gbox(lwgeom, &lwgeom_gbox);
+
+ if (!gbox_overlaps_2d(&lwgeom_gbox, &bgbox))
+ {
+ POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
+ return NULL;
+ }
+
+ if (!gbox_contains_2d(&bgbox, &lwgeom_gbox))
+ {
+ LWGEOM *clipped_geom =
+ lwgeom_clip_by_rect(lwgeom, bgbox.xmin, bgbox.ymin, bgbox.xmax, bgbox.ymax);
+ if (clipped_geom == NULL || lwgeom_is_empty(clipped_geom))
+ {
+ POSTGIS_DEBUG(3, "mvt_geom: no geometry after clip");
+ return NULL;
+ }
+
+ /* For some polygons, the simplify step might have left them
+ * as invalid, which can cause clipping to return the complementary
+ * geometry of what it should */
+ if ((basic_type == POLYGONTYPE) &&
+ !gbox_contains_2d(&lwgeom_gbox, lwgeom_get_bbox(clipped_geom)))
+ {
+ /* TODO: Adapt this when and if Exception Policies are introduced.
+ * Other options would be to fix the geometry and retry
+ * or to calculate the difference between the 2 boxes.
+ */
+ POSTGIS_DEBUG(3, "mvt_geom: Invalid geometry after clipping");
+ lwgeom_free(clipped_geom);
+ return NULL;
+ }
+
+ ng = clipped_geom;
+ }
+ }
+
+ if (basic_type == POLYGONTYPE)
+ {
+ /* Force validation as per MVT spec */
+ ng = lwgeom_make_valid(ng);
+
+ /* In image coordinates CW actually comes out a CCW, so we reverse */
+ lwgeom_force_clockwise(ng);
+ lwgeom_reverse_in_place(ng);
+ }
+
+ /* Make sure we return the most basic type after simplification and validation */
+ ng = lwgeom_to_basic_type(ng, basic_type);
+ if (basic_type != lwgeom_get_basic_type(ng))
+ {
+ /* Drop type changes to play nice with MVT renderers */
+ POSTGIS_DEBUG(3, "mvt_geom: Dropping geometry after type change");
+ return NULL;
+ }
+
+ /* Clipping and validation might produce float values. Grid again into int
+ * and pray that the output is still valid */
+ {
+ gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0};
+ lwgeom_grid_in_place(ng, &grid);
+ }
+
+ return ng;
+}
+
/**
* Transform a geometry into vector tile coordinate space.
*
LWGEOM *mvt_geom(LWGEOM *lwgeom, const GBOX *gbox, uint32_t extent, uint32_t buffer,
bool clip_geom)
{
- AFFINE affine;
- gridspec grid;
+ AFFINE affine = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0};
double width = gbox->xmax - gbox->xmin;
double height = gbox->ymax - gbox->ymin;
double resx, resy, res, fx, fy;
const uint8_t basic_type = lwgeom_get_basic_type(lwgeom);
POSTGIS_DEBUG(2, "mvt_geom called");
+ /* Simplify it as soon as possible */
+ lwgeom = lwgeom_to_basic_type(lwgeom, basic_type);
+
/* Short circuit out on EMPTY */
if (lwgeom_is_empty(lwgeom))
return NULL;
if (lwgeom_is_empty(lwgeom))
return NULL;
- if (clip_geom)
- {
- // We need to add an extra half pixel to include the points that
- // fall into the bbox only after the coordinate transformation
- double buffer_map_xunits = nextafterf(res, 0.0) + resx * buffer;
- GBOX bgbox;
- const GBOX *lwgeom_gbox = lwgeom_get_bbox(lwgeom);
- bgbox = *gbox;
- gbox_expand(&bgbox, buffer_map_xunits);
- if (!gbox_overlaps_2d(lwgeom_gbox, &bgbox))
- {
- POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
- return NULL;
- }
- if (!gbox_contains_2d(&bgbox, lwgeom_gbox))
- {
- double x0 = bgbox.xmin;
- double y0 = bgbox.ymin;
- double x1 = bgbox.xmax;
- double y1 = bgbox.ymax;
- const GBOX pre_clip_box = *lwgeom_get_bbox(lwgeom);
- LWGEOM *clipped_geom = lwgeom_clip_by_rect(lwgeom, x0, y0, x1, y1);
- if (clipped_geom == NULL || lwgeom_is_empty(clipped_geom))
- {
- POSTGIS_DEBUG(3, "mvt_geom: no geometry after clip");
- return NULL;
- }
- /* For some polygons, the simplify step might have left them
- * as invalid, which can cause clipping to return the complementary
- * geometry of what it should */
- if ((basic_type == POLYGONTYPE) &&
- !gbox_contains_2d(&pre_clip_box, lwgeom_get_bbox(clipped_geom)))
- {
- /* TODO: Adapt this when and if Exception Policies are introduced.
- * Other options would be to fix the geometry and retry
- * or to calculate the difference between the 2 boxes.
- */
- POSTGIS_DEBUG(3, "mvt_geom: Invalid geometry after clipping");
- lwgeom_free(clipped_geom);
- return NULL;
- }
- lwgeom = clipped_geom;
- }
- }
-
/* transform to tile coordinate space */
- memset(&affine, 0, sizeof(affine));
affine.afac = fx;
affine.efac = fy;
affine.ifac = 1;
lwgeom_affine(lwgeom, &affine);
/* snap to integer precision, removing duplicate points */
- memset(&grid, 0, sizeof(gridspec));
- grid.ipx = 0;
- grid.ipy = 0;
- grid.xsize = 1;
- grid.ysize = 1;
lwgeom_grid_in_place(lwgeom, &grid);
if (lwgeom == NULL || lwgeom_is_empty(lwgeom))
return NULL;
-
- if (basic_type == POLYGONTYPE)
- {
- /* Force validation as per MVT spec */
- lwgeom = lwgeom_make_valid(lwgeom);
-
- /* In image coordinates CW actually comes out a CCW, so we reverse */
- lwgeom_force_clockwise(lwgeom);
- lwgeom_reverse_in_place(lwgeom);
- }
-
- /* if geometry collection extract highest dimensional geometry type */
- lwgeom = lwgeom_to_basic_type(lwgeom, basic_type);
-
- if (basic_type != lwgeom_get_basic_type(lwgeom))
- {
- /* Drop type changes to play nice with MVT renderers */
- POSTGIS_DEBUG(3, "mvt_geom: Dropping geometry after type change");
- return NULL;
- }
-
+ lwgeom = mvt_clip_and_validate_geos(lwgeom, basic_type, extent, buffer, clip_geom);
if (lwgeom == NULL || lwgeom_is_empty(lwgeom))
return NULL;
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096*4096, 4096*4096)),
4096, 0, false));
select 'PG6', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON ((762780 6474467, 717821 6797045, 1052826 6797045, 762780 6474467))'),
+ ST_GeomFromText('POLYGON ((1052826 6797045, 762780 6474467, 717821 6797045, 1052826 6797045))'),
ST_MakeBox2D(ST_Point(626172.135625, 6261721.35625), ST_Point(1252344.27125, 6887893.49188)),
4096, 0, false));
-select 'PG7', ST_AsText(ST_AsMVTGeom(
+
+SELECT 'PG7', ST_AsText(ST_AsMVTGeom(
ST_GeomFromText('POLYGON((-7792023.4539488 1411512.60791779,-7785283.40665468 1406282.69482469,-7783978.88137195 1404858.20373788,-7782986.89858399 1402324.91434802,-7779028.02672366 1397370.31802772,
-7778652.06985644 1394387.75452545,-7779906.76953697 1393279.22658385,-7782212.33678782 1393293.14086794,-7784631.14401331 1394225.4151684,-7786257.27108231 1395867.40241344,-7783978.88137195 1395867.40241344,
-7783978.88137195 1396646.68250521,-7787752.03959369 1398469.72134299,-7795443.30325373 1405280.43988858,-7797717.16326269 1406217.73286975,-7798831.44531677 1406904.48130551,-7799311.5830898 1408004.24038921,
-7799085.10302919 1409159.72782477,-7798052.35381919 1411108.84582812,-7797789.63692662 1412213.40365339,-7798224.47868753 1414069.89725829,-7799003.5701851 1415694.42577482,-7799166.63587328 1416966.26267896,
-7797789.63692662 1417736.81850415,-7793160.38395328 1412417.61222784,-7792023.4539488 1411512.60791779))'),
ST_MakeBox2D(ST_Point(-20037508.34, -20037508.34), ST_Point(20037508.34, 20037508.34)),
- 4096, 10, true));
+ 4096, 10, true)) as g;
+
select 'PG8', ST_AsText(ST_AsMVTGeom(
ST_GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON (((0 0, 10 0, 10 5, 0 -5, 0 0))))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
4096, 0, false));
-select 'PG9', ST_AsText(ST_AsMVTGeom(
+select 'PG9', ST_Area(ST_AsMVTGeom(
ST_GeomFromText('POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(5, 5)),
4096, 0, true));
+
+-- There shoulnd't be floating point values
+WITH geometry AS
+(
+ SELECT ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((5 0, 0 5, 0 0, 5 5, 5 0))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(5, 5)),
+ 5, 0, true) as g
+)
+SELECT 'PG9.1', ST_NumGeometries(g), ST_Area(g), ST_AsText(g) LIKE '%2.5%'as fvalue FROM geometry;
SELECT 'PG10', ST_AsText(ST_AsMVTGeom(
'POINT EMPTY'::geometry,
'BOX(0 0,2 2)'::box2d));
-- Clockwise Polygon
SELECT 'PG11', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'),
+ ST_GeomFromText('POLYGON((10 10, 10 0, 0 0, 0 10, 10 10))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
-- Input: Exterior CW, interior CW
-- Output: CW, CCW
SELECT 'PG13', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 9, 9 9, 9 1, 1 1))'),
+ ST_GeomFromText('POLYGON((10 10, 10 0, 0 0, 0 10, 10 10), (9 9, 9 1, 1 1, 1 9, 9 9))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
-- Input: Exterior CW, interior CCW
-- Output: CW, CCW
SELECT 'PG14', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 9 1, 9 9, 1 9, 1 1))'),
+ ST_GeomFromText('POLYGON((10 10, 10 0, 0 0, 0 10, 10 10), (1 1, 9 1, 9 9, 1 9, 1 1))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
-- Input: Exterior CCW, interior CW
-- Output: CW, CCW
SELECT 'PG15', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 9, 9 9, 9 1, 1 1))'),
+ ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (9 9, 9 1, 1 1, 1 9, 9 9))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
-- Input: Exterior CCW, interior CW
-- Output: CW, CCW
SELECT 'PG16', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 9, 9 9, 9 1, 1 1))'),
+ ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (9 9, 9 1, 1 1, 1 9, 9 9))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
-- Input: CW, CW, CW, CW
-- Output: CW, CCW, CW, CCW
-SELECT 'PG17', ST_AsText(ST_AsMVTGeom(
+SELECT 'PG17', ST_Area(ST_AsMVTGeom(
ST_GeomFromText('POLYGON(
- (0 0, 0 10, 10 10, 10 0, 0 0),
- (1 1, 1 9, 9 9, 9 1, 1 1),
- (2 2, 2 8, 8 8, 8 2, 2 2),
- (3 3, 3 7, 7 7, 7 3, 3 3))'),
+ (10 10, 10 0, 0 0, 0 10, 10 10),
+ (9 9, 1 9, 1 1, 9 1, 9 9),
+ (8 8, 8 2, 2 2, 2 8, 8 8),
+ (7 7, 7 3, 3 3, 3 7, 7 7))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(10, 10)),
10, 0, false));
4096, 256, true));
SELECT 'PG36', ST_AsText(ST_AsMVTGeom(
- ST_Point(4352.49, -256.50),
+ ST_Point(4352.49, -256.51),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
4096, 256, true));
SELECT 'PG37', ST_AsText(ST_AsMVTGeom(
- ST_Point(4352.50, -256.49),
+ ST_Point(4352.51, -256.49),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
4096, 256, true));
SELECT 'PG38', ST_AsText(ST_AsMVTGeom(
- ST_Point(4352.50, -256.50),
+ ST_Point(4352.51, -256.51),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
4096, 256, true));
SELECT 'PG39 - ON ', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 100, 100 100, 100 90, 94 90, 94 96, 90 96, 90 80, 100 80, 100 0, 0 0, 0 100))'),
+ ST_GeomFromText('POLYGON((100 100, 100 90, 94 90, 94 96, 90 96, 90 80, 100 80, 100 0, 0 0, 0 100, 100 100))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
10, 0, true));
SELECT 'PG39 - OFF', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('POLYGON((0 100, 100 100, 100 90, 94 90, 94 96, 90 96, 90 80, 100 80, 100 0, 0 0, 0 100))'),
+ ST_GeomFromText('POLYGON((100 100, 100 90, 94 90, 94 96, 90 96, 90 80, 100 80, 100 0, 0 0, 0 100, 100 100))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
10, 0, false));
-- Geometry type change of one geometry of the multipolygon used to fallback to multilinestring
SELECT 'PG46', St_AsEWKT(ST_AsMVTGeom(
- 'SRID=3857;MULTIPOLYGON(((-8230324.85567616 4984496.35685962,-8230307.1114228 4984654.46474466,-8230285.21085987 4984959.60349704,-8230324.85567616 4984496.35685962)),((-8230327.54013683 4984444.33052449,-8230327.23971431 4984450.39401942,-8230327.26833036 4984449.87731981,-8230327.54013683 4984444.33052449)))'::geometry,
+ 'SRID=3857;MULTIPOLYGON(((-8230285.21085987 4984959.60349704,-8230324.85567616 4984496.35685962,-8230307.1114228 4984654.46474466,-8230285.21085987 4984959.60349704)),((-8230327.54013683 4984444.33052449,-8230327.23971431 4984450.39401942,-8230327.26833036 4984449.87731981,-8230327.54013683 4984444.33052449)))'::geometry,
'SRID=3857;POLYGON((-8238077.16046316 4989809.20645631,-8238077.16046316 4980025.2668358,-8228293.22084265 4980025.2668358,-8228293.22084265 4989809.20645631,-8238077.16046316 4989809.20645631))'::geometry,
4096,
16,
true));
--- Geometry fastpath
+-- Check polygon clipping
+--- Outside the tile
SELECT 'PG47', ST_AsText(ST_AsMVTGeom(
- ST_GeomFromText('LINESTRING(0 0, 0 4, 4 4, 4 0, 0 0)'),
- ST_MakeBox2D(ST_Point(0, 0), ST_Point(1000, 1000)),
- 100, 0, false));
+ ST_GeomFromText('POLYGON((-10 -10, -10 -5, -5 -5, -5 -10, -10 -10))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Outside the tile
+SELECT 'PG48', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((10 -10, 10 -5, 5 -5, 5 -10, 10 -10))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Outside the tile
+SELECT 'PG49', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((110 110, 110 105, 105 105, 105 110, 110 110))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Outside the tile
+SELECT 'PG50', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((10 -5, 10 0, 5 0, 5 -5, 10 -5))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Fully covers the tile
+SELECT 'PG51', ST_Area(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((-10 110, -10 -10, 110 -10, 110 110, -10 110))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Partially in the tile
+SELECT 'PG52', ST_Area(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((20 -10, 110 -10, 110 110, 20 110, 20 -10))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+--- Partially in the tile
+SELECT 'PG53', ST_Area(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((-20 10, 20 10, 20 40, -20 40, -20 10))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+-- Simplification
+SELECT 'PG54', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((0 10, 100 10, 100 10.3, 0 10))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG55', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((0 99.9, 99.9 99.9, 99.9 150, 0 150, 0 99.9))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG56', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((0 0, 99.6 100, 100 99.6, 0 0))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+-- This clips in float
+SELECT 'PG57', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('POLYGON((0 0, 0 99, 1 101, 100 100, 100 0, 0 0))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+-- Geometrycollection test
+SELECT 'PG58', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))), POINT(50 50))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG59', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(POINT(50 50), LINESTRING(10 10, 20 20), MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG60', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(POINT(50 50), GEOMETRYCOLLECTION(POINT(50 50), MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG61', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(POINT(50 50), MULTIPOLYGON(((100 100, 110 100, 110 110, 100 110, 100 100))))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG62', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(LINESTRING(10 10, 20 20), POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)), LINESTRING(20 20, 15 15))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG63', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(LINESTRING(10 10, 20 20), POLYGON((90 90, 110 90, 110 110, 90 110, 90 90)), LINESTRING(20 20, 15 15))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
+
+SELECT 'PG64', ST_AsText(ST_AsMVTGeom(
+ ST_GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON EMPTY, POINT(50 50))'),
+ ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
+ 100, 0, true));
-- geometry encoding tests
SELECT 'TG1', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1,
ST_AsMVTGeom(ST_GeomFromText('MULTILINESTRING((1 1, 501 501, 1001 1001),(2 2, 502 502, 1002 1002))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false) AS geom) AS q;
SELECT 'TG6', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1,
- ST_AsMVTGeom(ST_GeomFromText('POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30))'),
+ ST_AsMVTGeom(ST_GeomFromText('POLYGON ((45 45, 15 40, 10 20, 35 10, 45 45), (35 35, 30 20, 20 30, 35 35))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false) AS geom) AS q;
SELECT 'TG7', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1,
- ST_AsMVTGeom(ST_GeomFromText('MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)))'),
+ ST_AsMVTGeom(ST_GeomFromText('MULTIPOLYGON(((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (20 25, 30 20, 20 15, 20 25)), ((20 45, 45 30, 40 40, 20 45)))'),
ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false) AS geom) AS q;
SELECT 'TG8', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1,
ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
FROM (SELECT NULL::integer AS c1, NULL AS geom) AS q;
-- Ticket #3922
-SELECT '#3922', St_AsEWKT(ST_AsMVTGeom(
+SELECT '#3922', St_Area(ST_AsMVTGeom(
st_geomfromtwkb('\x06000104a501d0a7db06dad0940120ee030660229604109c010ed6011246143e76201a22b401a601f001b801580ef40122d803ca01de0cf00e80049204ac02b602be0138ca08bc02d605d201d2013cb804a401be013c9c03cd028608c106f001c1018601c7011e970125f10207439b02850a76ff0415030d0725431973132f227768671a5f133f17290865e405ba0154ab030415348502cc038d120c37d326c706850896109f01e201350f6f0a1903930165830121412d052928651d2b0d0f1107170b490c33120f010f0813034f47f50259190181031b3713ed04d901bd01439b02639507c10201021062054c1d3c101e6a0c2000684e6a7c1a681f443d160f044f0f490f03020b08051c01080c0e18013a012801380e08005808522d3a4c1c062a0f0e192a190a3b22194803261c1376122ac201d8011a101c065a17a8011c303206460c164a18a4015c56620801162d1404a402c601262a143002421222290f7b581d0719011d0311002908250a25021d030f0111030f05a3014315050d05110383011b9d011f3309a70347170325058b03417515130361190b4e19b40105fe208810041314041018270705c0039d0416251a1213241b0ffd02f5029408d001990218110607100c070a0b0819031c263432302454322a1e262a101e2a521426101c0c10101210121e18341c321c2c1c26222230162a10320c280e3202080e26123e0a2c041a002805360002051e010807161b281b1e1312010213101b14150e0906130c331e3518250e250c230a1d0a110e091407140718031a0008031a03140112093a199a01199801052e04100a0c120a4a0c7e1e2406220c4e20b60236c8013014020c0510090a110e1b0e11140d18021c08261054261417080f082504a702ea012c58068801180e0f1477209301082f062f00271f0b4b17170311020d100b180d180b0c1502190019031f09512d9b01592a1f120d0c0f0a15126b0637060f100b16032c0a2a1410120c120a240014011a03160314001482010100810900311753478d0117218b02b3027a692223745b2a111e031e130403061902691aa50118752ea70158045818562cae0170202614200e2e208a012e6c4a154c33448b01242f34651e2b221d481f2017122334a1010a510f2b6d8d021d5f073304351233242bce01772a251c3106291b4b032110351c2324239c016f260f5c138a01074e14261422282844221c7a24779a022db90127450b174319b501019b015a61b00105782a4e2a7615741305313a14422a4a079c01519001c9019c013388017352291c371c4110497e26442a8a0108502a2e2e19100980011984010b0e01840136042e1a6a22781f32356813280104370a5b12a5012b533e0748244e3e54355c064a45880115289d01103904453e810127290b5103a70152174841680b10254814402a4e305e82017232581792010522512e2516370023380b9801125434584c2a3e5202042f4e390f2f0e050205001f0801380d00430515421744fd01311b16614c038001241a482c3e44061e0a3881012605244d0e2d5d291a192c5710759d01284b20150f752308530a7f198101113d145d1f13534727290a291f490f4b0215246b196929752d2f2581012675371d432f090c4d2c0d080b141f0a0034051401110735152921055940010a023c0c0c35030519270825382f104512753e014001ae013b041708356ced012a0f7c2d041d0415631507e501012f0a491327411d1b310811072947493d0843125f4b7b16'),
'SRID=3347;POLYGON((3658201 658873,3658201 5958872.97428571,8958201.49428571 5958872.97428571,8958201.49428571 658873,3658201 658873))'::geometry,
4096,
PG3|POINT(2 4092)
PG4|MULTIPOLYGON(((5 4096,10 4091,10 4096,5 4096)),((5 4096,0 4101,0 4096,5 4096)))
PG5|
-PG6|POLYGON((894 2704,600 594,2791 594,894 2704))
+PG6|POLYGON((2791 594,894 2704,600 594,2791 594))
PG7|POLYGON((1252 1904,1253 1905,1253 1906,1251 1904,1252 1904))
PG8|MULTIPOLYGON(((5 4096,10 4091,10 4096,5 4096)),((5 4096,0 4101,0 4096,5 4096)))
-PG9|POLYGON((0 4096,0 0,4096 0,4096 4096,0 4096))
+PG9|16777216
+PG9.1|2|12.5|f
PG10|
-PG11|POLYGON((0 10,0 0,10 0,10 10,0 10))
+PG11|POLYGON((10 0,10 10,0 10,0 0,10 0))
PG12|POLYGON((0 10,0 0,10 0,10 10,0 10))
-PG13|POLYGON((0 10,0 0,10 0,10 10,0 10),(1 9,9 9,9 1,1 1,1 9))
-PG14|POLYGON((0 10,0 0,10 0,10 10,0 10),(1 9,9 9,9 1,1 1,1 9))
-PG15|POLYGON((0 10,0 0,10 0,10 10,0 10),(1 9,9 9,9 1,1 1,1 9))
-PG16|POLYGON((0 10,0 0,10 0,10 10,0 10),(1 9,9 9,9 1,1 1,1 9))
-PG17|MULTIPOLYGON(((0 10,0 0,10 0,10 10,0 10),(1 9,9 9,9 1,1 1,1 9)),((2 8,2 2,8 2,8 8,2 8),(3 7,7 7,7 3,3 3,3 7)))
+PG13|POLYGON((10 0,10 10,0 10,0 0,10 0),(9 1,1 1,1 9,9 9,9 1))
+PG14|POLYGON((10 0,10 10,0 10,0 0,10 0),(1 9,9 9,9 1,1 1,1 9))
+PG15|POLYGON((0 10,0 0,10 0,10 10,0 10),(9 1,1 1,1 9,9 9,9 1))
+PG16|POLYGON((0 10,0 0,10 0,10 10,0 10),(9 1,1 1,1 9,9 9,9 1))
+PG17|56
PG18|MULTIPOINT(1 9,3 8)
PG19|MULTIPOINT(25 4079,26 4078)
PG20|POINT(10 4086)
PG36|
PG37|
PG38|
-PG39 - ON |POLYGON((0 0,10 0,9 2,10 2,10 10,0 10,0 0))
-PG39 - OFF|POLYGON((0 0,10 0,9 2,10 2,10 10,0 10,0 0))
+PG39 - ON |POLYGON((10 0,9 2,10 2,10 10,0 10,0 0,10 0))
+PG39 - OFF|POLYGON((10 0,9 2,10 2,10 10,0 10,0 0,10 0))
PG40 - ON |LINESTRING(0 10,0 0)
PG40 - OFF|LINESTRING(0 10,0 0)
PG41 - ON |LINESTRING(0 10,0 4,0 2,0 0,1 0)
PG41 - OFF|LINESTRING(0 10,0 4,0 2,0 0,1 0)
PG42 - ON |LINESTRING(0 10,0 0,1 0)
PG42 - OFF|LINESTRING(0 10,0 0,1 0)
-PG43 - ON |MULTIPOLYGON(((5 5,0 0,10 0,5 5)),((0 10,5 5,10 10,0 10)))
+PG43 - ON |MULTIPOLYGON(((5 5,0 0,10 0,5 5)),((5 5,10 10,0 10,5 5)))
PG43 - OFF|MULTIPOLYGON(((5 5,-1 -1,11 -1,5 5)),((5 5,11 11,-1 11,5 5)))
PG44|
PG45|
-PG46|SRID=3857;POLYGON((3245 2224,3262 2030,3253 2158,3245 2224))
+PG46|SRID=3857;POLYGON((3262 2030,3253 2158,3245 2224,3262 2030))
PG47|
+PG48|
+PG49|
+PG50|
+PG51|10000
+PG52|8000
+PG53|600
+PG54|
+PG55|
+PG56|
+PG57|POLYGON((0 1,0 0,100 0,100 100,0 100,0 1))
+PG58|POLYGON((0 100,0 90,10 90,10 100,0 100))
+PG59|POLYGON((0 100,0 90,10 90,10 100,0 100))
+PG60|POLYGON((0 100,0 90,10 90,10 100,0 100))
+PG61|
+PG62|POLYGON((0 100,0 90,10 90,10 100,0 100))
+PG63|POLYGON((90 0,100 0,100 10,90 10,90 0))
+PG64|
TG1|GiEKBHRlc3QSDBICAAAYASIECTLePxoCYzEiAigBKIAgeAI=
TG2|GiMKBHRlc3QSDhICAAAYASIGETLePwIBGgJjMSICKAEogCB4Ag==
TG3|GiYKBHRlc3QSERICAAAYAiIJCQCAQArQD88PGgJjMSICKAEogCB4Ag==
TG4|GiYKBHRlc3QSERICAAAYAiIJCQCAQArQD88PGgJjMSICKAEogCB4Ag==
TG5|GjAKBHRlc3QSGxICAAAYAiITCQL+PwrQD88PCc0Pzg8K0A/PDxoCYzEiAigBKIAgeAI=
-TG6|GjIKBHRlc3QSHRICAAAYAyIVCUbsPxoxEwonPAkPCTEeEhQUCh0PGgJjMSICKAEogCB4Ag==
-TG7|Gj0KBHRlc3QSKBICAAAYAyIgCVCwPxIKFDEdDwkAFCIyHh0eJwkAJw8JKBQSEwkAFA8aAmMxIgIo
+TG6|GjIKBHRlc3QSHRICAAAYAyIVCVqmPxoTRjETCicPCSgKEh0KFBQPGgJjMSICKAEogCB4Ag==
+TG7|Gj0KBHRlc3QSKBICAAAYAyIgCSi6PyIyHh0eJwkAJw8JFAoSABQUCQ8JEzESKAoKFA8aAmMxIgIo
ASiAIHgC
TG8|GiEKBHRlc3QSDBICAAAYASIECTLePxoCYzEiAigBKIAgeAI=
TG9|GiMKBHRlc3QSDhICAAAYASIGETLeP2VGGgJjMSICKAEogCB4Ag==
TU2
ERROR: pgis_asmvt_transfn: parameter row cannot be other than a rowtype
TU3|
-#3922|POLYGON((2613 3664,2615 3662,2616 3662,2617 3665,2615 3665,2615 3664,2613 3664))
+#3922|6.5
FI1|GicKBHRlc3QSDggBEgIAABgBIgQJMt4/GgJjMiIGCgRhYmNkKIAgeAI=
FI2|GicKBHRlc3QSDggBEgIAABgBIgQJMt4/GgJjMiIGCgRhYmNkKIAgeAI=
FI3|GicKBHRlc3QSDggBEgIAABgBIgQJMt4/GgJjMiIGCgRhYmNkKIAgeAI=