]> granicus.if.org Git - postgis/commitdiff
Rework ST_AsMVTGeom clipping logic
authorBjörn Harrtell <bjorn@wololo.org>
Fri, 28 Apr 2017 21:07:50 +0000 (21:07 +0000)
committerBjörn Harrtell <bjorn@wololo.org>
Fri, 28 Apr 2017 21:07:50 +0000 (21:07 +0000)
Closes #3740

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

postgis/lwgeom_out_mvt.c
postgis/mvt.c
regress/mvt.sql
regress/mvt_expected

index b797773c83f466f3e02bbeda480b02be94585a61..107ce428e096aea00d7a97a3ab7fc44520870081 100644 (file)
@@ -62,6 +62,8 @@ Datum ST_AsMVTGeom(PG_FUNCTION_ARGS)
        clip_geom = PG_ARGISNULL(4) ? true : PG_GETARG_BOOL(4);
        lwgeom_out = mvt_geom(lwgeom_in, bounds, extent, buffer, clip_geom);
        lwgeom_free(lwgeom_in);
+       if (lwgeom_out == NULL)
+               PG_RETURN_NULL();
        geom_out = geometry_serialize(lwgeom_out);
        lwgeom_free(lwgeom_out);
        PG_FREE_IF_COPY(geom_in, 0);
index a2e039ff645c91adc458fa507647b6e9d384e4c4..d125d0024832c9e6f1ec717c84b73c644552deca 100644 (file)
@@ -497,6 +497,9 @@ LWGEOM *mvt_geom(LWGEOM *lwgeom, GBOX *gbox, uint32_t extent, uint32_t buffer,
        double resy = height / extent;
        double fx = extent / width;
        double fy = -(extent / height);
+       double buffer_map_xunits = resx * buffer;
+       double buffer_map_yunits = resy * buffer;
+       const GBOX *ggbox = lwgeom_get_bbox(lwgeom);
 
        if (width == 0 || height == 0)
                lwerror("mvt_geom: bounds width or height cannot be 0");
@@ -505,19 +508,28 @@ LWGEOM *mvt_geom(LWGEOM *lwgeom, GBOX *gbox, uint32_t extent, uint32_t buffer,
                lwerror("mvt_geom: extent cannot be 0");
 
        if (clip_geom) {
-               double buffer_map_xunits = resx * buffer;
-               double buffer_map_yunits = resy * buffer;
-               double x0 = gbox->xmin - buffer_map_xunits;
-               double y0 = gbox->ymin - buffer_map_yunits;
-               double x1 = gbox->xmax + buffer_map_xunits;
-               double y1 = gbox->ymax + buffer_map_yunits;
+               GBOX *bgbox = gbox_copy(gbox);
+               gbox_expand(bgbox, buffer_map_xunits);
+               if (!gbox_overlaps_2d(ggbox, bgbox)) {
+                       POSTGIS_DEBUG(3, "mvt_geom: geometry outside clip box");
+                       return NULL;
+               }
+               if (!gbox_contains_2d(bgbox, ggbox)) {
+                       double x0 = bgbox->xmin;
+                       double y0 = bgbox->ymin;
+                       double x1 = bgbox->xmax;
+                       double y1 = bgbox->ymax;
 #if POSTGIS_GEOS_VERSION < 35
-               LWPOLY *lwenv = lwpoly_construct_envelope(0, x0, y0, x1, y1);
-               lwgeom = lwgeom_intersection(lwgeom, lwpoly_as_lwgeom(lwenv));
-               lwpoly_free(lwenv);
+                       LWPOLY *lwenv = lwpoly_construct_envelope(0, x0, y0, x1, y1);
+                       lwgeom = lwgeom_intersection(lwgeom, lwpoly_as_lwgeom(lwenv));
+                       lwpoly_free(lwenv);
 #else
-               lwgeom = lwgeom_clip_by_rect(lwgeom, x0, y0, x1, y1);
+                       lwgeom = lwgeom_clip_by_rect(lwgeom, x0, y0, x1, y1);
 #endif
+                       POSTGIS_DEBUG(3, "mvt_geom: no geometry after clip");
+                       if (lwgeom == NULL || lwgeom_is_empty(lwgeom))
+                               return NULL;
+               }
        }
 
        AFFINE affine;
@@ -552,6 +564,9 @@ LWGEOM *mvt_geom(LWGEOM *lwgeom, GBOX *gbox, uint32_t extent, uint32_t buffer,
                lwgeom_out = lwgeom_homogenize(lwgeom_out);
        }
 
+       if (lwgeom == NULL || lwgeom_is_empty(lwgeom))
+               return NULL;
+
        return lwgeom_out;
 }
 
index 68b156d661b20e8c1ff8db9e18f7933d32968e02..4dc84fa87e4b3e95b1a475b561451dba498a2ae4 100644 (file)
@@ -35,6 +35,10 @@ 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(
+       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));
 
 -- geometry encoding tests
 SELECT 'TG1', encode(ST_AsMVT('test', 4096, 'geom', q), 'base64') FROM (SELECT 1 AS c1,
index b90af1bdb143e51dee0578a9e30cad77c5df704d..2f20a13877ca04307fa736e6afd32a5cfb6fd47f 100644 (file)
@@ -6,6 +6,7 @@ PG5|POINT(0 4096)
 PG6|POLYGON((894 2704,2791 594,600 594,894 2704))
 PG7|POLYGON((1252 1904,1251 1904,1252 1905,1253 1906,1253 1905,1252 1904))
 PG8|MULTIPOLYGON(((5 4096,10 4096,10 4091,5 4096)),((0 4096,0 4101,5 4096,0 4096)))
+PG9|POLYGON((0 4096,4096 4096,4096 0,0 0,0 4096))
 TG1|GiEKBHRlc3QSDBICAAAYASIECTLePxoCYzEiAigBKIAgeAI=
 TG2|GiMKBHRlc3QSDhICAAAYASIGETLePwIBGgJjMSICKAEogCB4Ag==
 TG3|GiYKBHRlc3QSERICAAAYAiIJCQCAQArQD88PGgJjMSICKAEogCB4Ag==