<br><br><div class="gmail_quote"><div dir="ltr">On ср, 3 кас 2018, 07:11 Raul <raul@rmr.ninja> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: algunenano<br>
Date: 2018-10-03 04:11:12 -0700 (Wed, 03 Oct 2018)<br>
New Revision: 16877<br>
<br>
Modified:<br>
   branches/2.5/postgis/mvt.c<br>
   branches/2.5/regress/mvt.sql<br>
   branches/2.5/regress/mvt_expected<br>
Log:<br>
St_AsMVTGeom: Handle type changes in geometry collections<br>
<br>
References #4181<br>
<br>
<br>
Modified: branches/2.5/postgis/mvt.c<br>
===================================================================<br>
--- branches/2.5/postgis/mvt.c  2018-10-03 10:52:58 UTC (rev 16876)<br>
+++ branches/2.5/postgis/mvt.c  2018-10-03 11:11:12 UTC (rev 16877)<br>
@@ -727,6 +727,39 @@<br>
        POSTGIS_DEBUGF(3, "parse_values n_tags %zd", ctx->feature->n_tags);<br>
 }<br>
<br>
+/* For a given geometry, look for the highest dimensional basic type, that is,<br>
+ * point, line or polygon */<br>
+static uint8<br>
+lwgeom_get_basic_type(LWGEOM *geom)<br></blockquote></div><div><br></div><div>It looks like lwgeom_dimensionality which is also a copy of lwgeom_dimension? </div><div><br></div><div><br></div><div><br></div><div><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+{<br>
+       switch(geom->type)<br>
+       {<br>
+       case POINTTYPE:<br>
+       case LINETYPE:<br>
+       case POLYGONTYPE:<br>
+               return geom->type;<br>
+       case MULTIPOINTTYPE:<br>
+       case MULTILINETYPE:<br>
+       case MULTIPOLYGONTYPE:<br>
+               return geom->type - 3; /* Based on LWTYPE positions */<br>
+       case COLLECTIONTYPE:<br>
+       {<br>
+               uint32_t i;<br>
+               uint8 type = 0;<br>
+               LWCOLLECTION *g = (LWCOLLECTION*)geom;<br>
+               for (i = 0; i < g->ngeoms; i++)<br>
+               {<br>
+                       LWGEOM *sg = g->geoms[i];<br>
+                       type = Max(type, lwgeom_get_basic_type(sg));<br>
+               }<br>
+               return type;<br>
+       }<br>
+       default:<br>
+               elog(ERROR, "%s: Invalid type (%d)", __func__, geom->type);<br>
+       }<br>
+}<br>
+<br>
+<br>
 /**<br>
  * In place process a collection to find a concrete geometry<br>
  * object and expose that as the actual object. Will some<br>
@@ -734,27 +767,12 @@<br>
  * draw it anyways.<br>
  */<br>
 static void<br>
-lwgeom_to_basic_type(LWGEOM *geom)<br>
+lwgeom_to_basic_type(LWGEOM *geom, uint8 original_type)<br>
 {<br>
        if (lwgeom_get_type(geom) == COLLECTIONTYPE)<br>
        {<br>
-               /* MVT doesn't handle generic collections, so we */<br>
-               /* need to strip them down to a typed collection */<br>
-               /* by finding the largest basic type available and */<br>
-               /* using that as the basis of a typed collection. */<br>
                LWCOLLECTION *g = (LWCOLLECTION*)geom;<br>
-               LWCOLLECTION *gc;<br>
-               uint32_t i, maxtype = 0;<br>
-               for (i = 0; i < g->ngeoms; i++)<br>
-               {<br>
-                       LWGEOM *sg = g->geoms[i];<br>
-                       if (sg->type > maxtype && sg->type < COLLECTIONTYPE)<br>
-                               maxtype = sg->type;<br>
-               }<br>
-               if (maxtype > 3) maxtype -= 3;<br>
-               /* Force the working geometry to be a simpler version */<br>
-               /* of itself */<br>
-               gc = lwcollection_extract(g, maxtype);<br>
+               LWCOLLECTION *gc = lwcollection_extract(g, original_type);<br>
                *g = *gc;<br>
        }<br>
 }<br>
@@ -776,6 +794,7 @@<br>
        double height = gbox->ymax - gbox->ymin;<br>
        double resx, resy, res, fx, fy;<br>
        int preserve_collapsed = LW_TRUE;<br>
+       const uint8_t basic_type = lwgeom_get_basic_type(lwgeom);<br>
        POSTGIS_DEBUG(2, "mvt_geom called");<br>
<br>
        /* Short circuit out on EMPTY */<br>
@@ -832,9 +851,7 @@<br>
                        /* For some polygons, the simplify step might have left them<br>
                         * as invalid, which can cause clipping to return the complementary<br>
                         * geometry of what it should */<br>
-                       if ((lwgeom->type == POLYGONTYPE ||<br>
-                               lwgeom->type == MULTIPOLYGONTYPE ||<br>
-                               lwgeom->type == COLLECTIONTYPE) &&<br>
+                       if ((basic_type == POLYGONTYPE) &&<br>
                            !gbox_contains_2d(&pre_clip_box, lwgeom_get_bbox(clipped_geom)))<br>
                        {<br>
                                /* TODO: Adapt this when and if Exception Policies are introduced.<br>
@@ -870,22 +887,11 @@<br>
                return NULL;<br>
<br>
<br>
-       if (lwgeom->type == POLYGONTYPE ||<br>
-               lwgeom->type == MULTIPOLYGONTYPE ||<br>
-               lwgeom->type == COLLECTIONTYPE)<br>
+       if (basic_type == POLYGONTYPE)<br>
        {<br>
                /* Force validation as per MVT spec */<br>
                lwgeom = lwgeom_make_valid(lwgeom);<br>
<br>
-               /* Drop type changes tp play nice with MVT renderers */<br>
-               if (!(lwgeom->type == POLYGONTYPE ||<br>
-                       lwgeom->type == MULTIPOLYGONTYPE ||<br>
-                       lwgeom->type == COLLECTIONTYPE))<br>
-               {<br>
-                       lwgeom_free(lwgeom);<br>
-                       return NULL;<br>
-               }<br>
-<br>
                /* In image coordinates CW actually comes out a CCW, so we reverse */<br>
                lwgeom_force_clockwise(lwgeom);<br>
                lwgeom_reverse_in_place(lwgeom);<br>
@@ -893,8 +899,15 @@<br>
<br>
        /* if geometry collection extract highest dimensional geometry type */<br>
        if (lwgeom->type == COLLECTIONTYPE)<br>
-               lwgeom_to_basic_type(lwgeom);<br>
+               lwgeom_to_basic_type(lwgeom, basic_type);<br>
<br>
+       if (basic_type != lwgeom_get_basic_type(lwgeom))<br>
+       {<br>
+               /* Drop type changes to play nice with MVT renderers */<br>
+               POSTGIS_DEBUG(3, "mvt_geom: Dropping geometry after type change");<br>
+               return NULL;<br>
+       }<br>
+<br>
        if (lwgeom == NULL || lwgeom_is_empty(lwgeom))<br>
                return NULL;<br>
<br>
<br>
Modified: branches/2.5/regress/mvt.sql<br>
===================================================================<br>
--- branches/2.5/regress/mvt.sql        2018-10-03 10:52:58 UTC (rev 16876)<br>
+++ branches/2.5/regress/mvt.sql        2018-10-03 11:11:12 UTC (rev 16877)<br>
@@ -273,6 +273,14 @@<br>
        16,<br>
        true));<br>
<br>
+-- Geometry type change of one geometry of the multipolygon used to fallback to multilinestring<br>
+SELECT 'PG46', St_AsEWKT(ST_AsMVTGeom(<br>
+       '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,<br>
+       'SRID=3857;POLYGON((-8238077.16046316 4989809.20645631,-8238077.16046316 4980025.2668358,-8228293.22084265 4980025.2668358,-8228293.22084265 4989809.20645631,-8238077.16046316 4989809.20645631))'::geometry,<br>
+       4096,<br>
+       16,<br>
+       true));<br>
+<br>
 -- geometry encoding tests<br>
 SELECT 'TG1', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT 1 AS c1,<br>
        ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),<br>
@@ -433,11 +441,11 @@<br>
        FROM (SELECT NULL::integer AS c1, NULL AS geom) AS q;<br>
<br>
 -- Ticket #3922<br>
-SELECT '#3922', length(bytea(ST_AsMVTGeom(<br>
+SELECT '#3922', St_AsEWKT(ST_AsMVTGeom(<br>
                st_geomfromtwkb('\x06000104a501d0a7db06dad0940120ee030660229604109c010ed6011246143e76201a22b401a601f001b801580ef40122d803ca01de0cf00e80049204ac02b602be0138ca08bc02d605d201d2013cb804a401be013c9c03cd028608c106f001c1018601c7011e970125f10207439b02850a76ff0415030d0725431973132f227768671a5f133f17290865e405ba0154ab030415348502cc038d120c37d326c706850896109f01e201350f6f0a1903930165830121412d052928651d2b0d0f1107170b490c33120f010f0813034f47f50259190181031b3713ed04d901bd01439b02639507c10201021062054c1d3c101e6a0c2000684e6a7c1a681f443d160f044f0f490f03020b08051c01080c0e18013a012801380e08005808522d3a4c1c062a0f0e192a190a3b22194803261c1376122ac201d8011a101c065a17a8011c303206460c164a18a4015c56620801162d1404a402c601262a143002421222290f7b581d0719011d0311002908250a25021d030f0111030f05a3014315050d05110383011b9d011f3309a70347170325058b03417515130361190b4e19b40105fe208810041314041018270705c0039d0416251a1213241b0ffd02f5029408d001990218110607100c070a0b0819031c263432302454322a1e262a101e2a521426101c0c10101210<br>
 121e18341c321c2c1c26222230162a10320c280e3202080e26123e0a2c041a002805360002051e010807161b281b1e1312010213101b14150e0906130c331e3518250e250c230a1d0a110e091407140718031a0008031a03140112093a199a01199801052e04100a0c120a4a0c7e1e2406220c4e20b60236c8013014020c0510090a110e1b0e11140d18021c08261054261417080f082504a702ea012c58068801180e0f1477209301082f062f00271f0b4b17170311020d100b180d180b0c1502190019031f09512d9b01592a1f120d0c0f0a15126b0637060f100b16032c0a2a1410120c120a240014011a03160314001482010100810900311753478d0117218b02b3027a692223745b2a111e031e130403061902691aa50118752ea70158045818562cae0170202614200e2e208a012e6c4a154c33448b01242f34651e2b221d481f2017122334a1010a510f2b6d8d021d5f073304351233242bce01772a251c3106291b4b032110351c2324239c016f260f5c138a01074e14261422282844221c7a24779a022db90127450b174319b501019b015a61b00105782a4e2a7615741305313a14422a4a079c01519001c9019c013388017352291c371c4110497e26442a8a0108502a2e2e19100980011984010b0e01840136042e1a6a22781f32356813280104370a5b12a5012b533e07482<br>
 44e3e54355c064a45880115289d01103904453e810127290b5103a70152174841680b10254814402a4e305e82017232581792010522512e2516370023380b9801125434584c2a3e5202042f4e390f2f0e050205001f0801380d00430515421744fd01311b16614c038001241a482c3e44061e0a3881012605244d0e2d5d291a192c5710759d01284b20150f752308530a7f198101113d145d1f13534727290a291f490f4b0215246b196929752d2f2581012675371d432f090c4d2c0d080b141f0a0034051401110735152921055940010a023c0c0c35030519270825382f104512753e014001ae013b041708356ced012a0f7c2d041d0415631507e501012f0a491327411d1b310811072947493d0843125f4b7b16'),<br>
                'SRID=3347;POLYGON((3658201 658873,3658201 5958872.97428571,8958201.49428571 5958872.97428571,8958201.49428571 658873,3658201 658873))'::geometry,<br>
                4096,<br>
                0,<br>
                true<br>
-               )));<br>
+               ));<br>
<br>
<br>
Modified: branches/2.5/regress/mvt_expected<br>
===================================================================<br>
--- branches/2.5/regress/mvt_expected   2018-10-03 10:52:58 UTC (rev 16876)<br>
+++ branches/2.5/regress/mvt_expected   2018-10-03 11:11:12 UTC (rev 16877)<br>
@@ -48,6 +48,7 @@<br>
 PG43 - OFF|MULTIPOLYGON(((5 5,-1 -1,11 -1,5 5)),((5 5,11 11,-1 11,5 5)))<br>
 PG44|<br>
 PG45|<br>
+PG46|SRID=3857;MULTIPOLYGON(((3245 2224,3262 2030,3253 2158,3245 2224)))<br>
 TG1|GiEKBHRlc3QSDBICAAAYASIECTLePxoCYzEiAigBKIAgeAI=<br>
 TG2|GiMKBHRlc3QSDhICAAAYASIGETLePwIBGgJjMSICKAEogCB4Ag==<br>
 TG3|GiYKBHRlc3QSERICAAAYAiIJCQCAQArQD88PGgJjMSICKAEogCB4Ag==<br>
@@ -97,4 +98,4 @@<br>
 TU2<br>
 ERROR:  pgis_asmvt_transfn: parameter row cannot be other than a rowtype<br>
 TU3|<br>
-#3922|91<br>
+#3922|MULTIPOLYGON(((2613 3664,2615 3662,2616 3662,2617 3665,2615 3665,2615 3664,2613 3664)))<br>
<br>
_______________________________________________<br>
postgis-tickets mailing list<br>
<a href="mailto:postgis-tickets@lists.osgeo.org" target="_blank">postgis-tickets@lists.osgeo.org</a><br>
<a href="https://lists.osgeo.org/mailman/listinfo/postgis-tickets" rel="noreferrer" target="_blank">https://lists.osgeo.org/mailman/listinfo/postgis-tickets</a></blockquote></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">Darafei Praliaskouski<br>Support me: <a href="http://patreon.com/komzpa">http://patreon.com/komzpa</a></div></div>