]> granicus.if.org Git - postgis/commitdiff
Add a regression test for ST_Subdivide
authorPaul Ramsey <pramsey@cleverelephant.ca>
Mon, 16 Mar 2015 19:59:20 +0000 (19:59 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Mon, 16 Mar 2015 19:59:20 +0000 (19:59 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13342 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/g_box.c
liblwgeom/liblwgeom.h.in
liblwgeom/liblwgeom_internal.h
liblwgeom/lwgeom.c
liblwgeom/lwpoly.c
postgis/lwgeom_functions_basic.c
regress/clipbybox2d.sql
regress/clipbybox2d_expected

index 43ae3fcc8c9e6b5564632cf719d0df94b9e9a971..e53579ee10819491e26ce7d6b05cfce224084433 100644 (file)
@@ -46,6 +46,16 @@ GBOX* gbox_clone(const GBOX *gbox)
        return g;
 }
 
+int gbox_has_z(const GBOX *gbox)
+{
+       return FLAGS_GET_Z(gbox->flags);
+}
+
+int gbox_has_m(const GBOX *gbox)
+{
+       return FLAGS_GET_M(gbox->flags);
+}
+
 /* TODO to be removed */
 BOX3D* box3d_from_gbox(const GBOX *gbox)
 {
index 44fe32b4764a93079e526d8fd3d4ba5b178cac75..ec9f3814d95a7ea5c3fc233a0224f3d94ff38796 100644 (file)
@@ -1042,6 +1042,10 @@ extern LWCOMPOUND* lwcompound_construct_from_lwline(const LWLINE *lwpoly);
 */
 extern LWCURVEPOLY* lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly);
 
+/**
+* Construct a new 2D polygon using an envelope as input 
+*/
+extern LWPOLY* lwpoly_construct_from_gbox(int srid, const GBOX *gbox);
 
 /******************************************************************
  * LWGEOM functions
index fff65278c362363dafe144c2abfd2e9dcffd443f..a5443e4115bb6f10c317cd9843c6ed3ca04e593e 100644 (file)
@@ -440,3 +440,5 @@ int ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox);
 int gbox_contains_point2d(const GBOX *g, const POINT2D *p);
 int lwgeom_npoints_in_rect(const LWGEOM *geom, const GBOX *gbox);
 int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt);
+int gbox_has_z(const GBOX *gbox);
+int gbox_has_m(const GBOX *gbox);
index 5a903252522b6edf5bb4b921c6c5032304400aa2..781bb29e0f08db45e1a223ad52fd1587d0dc8108 100644 (file)
@@ -372,14 +372,14 @@ void
 lwgeom_release(LWGEOM *lwgeom)
 {
        if ( ! lwgeom )
-               lwerror("lwgeom_release: someone called on 0x0");
+               lwerror("%s: someone called on 0x0", __func__);
 
        LWDEBUGF(3, "releasing type %s", lwtype_name(lwgeom->type));
 
        /* Drop bounding box (always a copy) */
        if ( lwgeom->bbox )
        {
-               LWDEBUGF(3, "lwgeom_release: releasing bbox. %p", lwgeom->bbox);
+               LWDEBUGF(3, "%s: releasing bbox. %p", __func__, lwgeom->bbox);
                lwfree(lwgeom->bbox);
        }
        lwfree(lwgeom);
@@ -421,7 +421,7 @@ lwgeom_clone(const LWGEOM *lwgeom)
        case COLLECTIONTYPE:
                return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
        default:
-               lwerror("lwgeom_clone: Unknown geometry type: %s", lwtype_name(lwgeom->type));
+               lwerror("%s: Unknown geometry type: %s", __func__, lwtype_name(lwgeom->type));
                return NULL;
        }
 }
@@ -456,7 +456,7 @@ lwgeom_clone_deep(const LWGEOM *lwgeom)
        case COLLECTIONTYPE:
                return (LWGEOM *)lwcollection_clone_deep((LWCOLLECTION *)lwgeom);
        default:
-               lwerror("lwgeom_clone_deep: Unknown geometry type: %s", lwtype_name(lwgeom->type));
+               lwerror("%s: Unknown geometry type: %s", __func__, lwtype_name(lwgeom->type));
                return NULL;
        }
 }
@@ -555,7 +555,7 @@ lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
                return lwcollection_same((LWCOLLECTION *)lwgeom1,
                                         (LWCOLLECTION *)lwgeom2);
        default:
-               lwerror("lwgeom_same: unsupported geometry type: %s",
+               lwerror("%s: unsupported geometry type: %s", __func__, 
                        lwtype_name(lwgeom1->type));
                return LW_FALSE;
        }
@@ -735,7 +735,7 @@ lwgeom_force_dims(const LWGEOM *geom, int hasz, int hasm)
                case COLLECTIONTYPE:
                        return lwcollection_as_lwgeom(lwcollection_force_dims((LWCOLLECTION*)geom, hasz, hasm));
                default:
-                       lwerror("lwgeom_force_2d: unsupported geom type: %s", lwtype_name(geom->type));
+                       lwerror("%s: unsupported geom type: %s", __func__, lwtype_name(geom->type));
                        return NULL;
        }
 }
@@ -893,7 +893,7 @@ lwgeom_set_geodetic(LWGEOM *geom, int value)
                                lwgeom_set_geodetic(col->geoms[i], value);
                        break;
                default:
-                       lwerror("lwgeom_set_geodetic: unsupported geom type: %s", lwtype_name(geom->type));
+                       lwerror("%s: unsupported geom type: %s", __func__, lwtype_name(geom->type));
                        return;
        }
 }
@@ -938,8 +938,8 @@ lwgeom_longitude_shift(LWGEOM *lwgeom)
                        lwgeom_longitude_shift(coll->geoms[i]);
                return;
        default:
-               lwerror("lwgeom_longitude_shift: unsupported geom type: %s",
-                       lwtype_name(lwgeom->type));
+               lwerror("%s: unsupported geom type: %s",
+                       __func__, lwtype_name(lwgeom->type));
        }
 }
 
@@ -1095,7 +1095,7 @@ void lwgeom_free(LWGEOM *lwgeom)
                lwcollection_free((LWCOLLECTION *)lwgeom);
                break;
        default:
-               lwerror("lwgeom_free called with unknown type (%d) %s", lwgeom->type, lwtype_name(lwgeom->type));
+               lwerror("%s called with unknown type (%d) %s", __func__, lwgeom->type, lwtype_name(lwgeom->type));
        }
        return;
 }
@@ -1144,8 +1144,8 @@ int lwgeom_count_vertices(const LWGEOM *geom)
        /* Null? Zero. */
        if( ! geom ) return 0;
        
-       LWDEBUGF(4, "lwgeom_count_vertices got type %s",
-                lwtype_name(geom->type));
+       LWDEBUGF(4, "%s got type %s",
+                __func__, lwtype_name(geom->type));
 
        /* Empty? Zero. */
        if( lwgeom_is_empty(geom) ) return 0;
@@ -1176,8 +1176,8 @@ int lwgeom_count_vertices(const LWGEOM *geom)
                result = lwcollection_count_vertices((LWCOLLECTION *)geom);
                break;
        default:
-               lwerror("lwgeom_count_vertices: unsupported input geometry type: %s",
-                       lwtype_name(geom->type));
+               lwerror("%s: unsupported input geometry type: %s",
+                       __func__, lwtype_name(geom->type));
                break;
        }
        LWDEBUGF(3, "counted %d vertices", result);
@@ -1195,8 +1195,8 @@ int lwgeom_dimension(const LWGEOM *geom)
        /* Null? Zero. */
        if( ! geom ) return -1;
        
-       LWDEBUGF(4, "lwgeom_dimension got type %s",
-                lwtype_name(geom->type));
+       LWDEBUGF(4, "%s got type %s",
+                __func__, lwtype_name(geom->type));
 
        /* Empty? Zero. */
        /* if( lwgeom_is_empty(geom) ) return 0; */
@@ -1237,8 +1237,8 @@ int lwgeom_dimension(const LWGEOM *geom)
                return maxdim;
        }
        default:
-               lwerror("lwgeom_dimension: unsupported input geometry type: %s",
-                       lwtype_name(geom->type));
+               lwerror("%s: unsupported input geometry type: %s",
+                       __func__, lwtype_name(geom->type));
        }
        return -1;
 }
@@ -1287,7 +1287,7 @@ int lwgeom_count_rings(const LWGEOM *geom)
                break;
        }
        default:
-               lwerror("lwgeom_count_rings: unsupported input geometry type: %s", lwtype_name(geom->type));
+               lwerror("%s: unsupported input geometry type: %s", __func__, lwtype_name(geom->type));
                break;
        }
        LWDEBUGF(3, "counted %d rings", result);
@@ -1297,8 +1297,8 @@ int lwgeom_count_rings(const LWGEOM *geom)
 int lwgeom_is_empty(const LWGEOM *geom)
 {
        int result = LW_FALSE;
-       LWDEBUGF(4, "lwgeom_is_empty: got type %s",
-                lwtype_name(geom->type));
+       LWDEBUGF(4, "%s: got type %s",
+                __func__, lwtype_name(geom->type));
 
        switch (geom->type)
        {
@@ -1330,8 +1330,8 @@ int lwgeom_is_empty(const LWGEOM *geom)
                return lwcollection_is_empty((LWCOLLECTION *)geom);
                break;
        default:
-               lwerror("lwgeom_is_empty: unsupported input geometry type: %s",
-                       lwtype_name(geom->type));
+               lwerror("%s: unsupported input geometry type: %s",
+                       __func__, lwtype_name(geom->type));
                break;
        }
        return result;
@@ -1363,8 +1363,8 @@ extern int lwgeom_dimensionality(LWGEOM *geom)
 {
        int dim;
 
-       LWDEBUGF(3, "lwgeom_dimensionality got type %s",
-                lwtype_name(geom->type));
+       LWDEBUGF(3, "%s got type %s",
+                __func__, lwtype_name(geom->type));
 
        switch (geom->type)
        {
@@ -1397,8 +1397,8 @@ extern int lwgeom_dimensionality(LWGEOM *geom)
                return lwcollection_dimensionality((LWCOLLECTION *)geom);
                break;
        default:
-               lwerror("lwgeom_dimensionality: unsupported input geometry type: %s",
-                       lwtype_name(geom->type));
+               lwerror("%s: unsupported input geometry type: %s",
+                       __func__, lwtype_name(geom->type));
                break;
        }
        return 0;
@@ -1442,8 +1442,8 @@ extern LWGEOM* lwgeom_remove_repeated_points(LWGEOM *in)
                return in;
 
        default:
-               lwnotice("lwgeom_remove_repeated_points: unsupported geometry type: %s",
-                        lwtype_name(in->type));
+               lwnotice("%s: unsupported geometry type: %s",
+                        __func__, lwtype_name(in->type));
                return in;
                break;
        }
@@ -1518,8 +1518,8 @@ void lwgeom_swap_ordinates(LWGEOM *in, LWORD o1, LWORD o2)
                break;
 
        default:
-               lwerror("lwgeom_swap_ordinates: unsupported geometry type: %s",
-                       lwtype_name(in->type));
+               lwerror("%s: unsupported geometry type: %s",
+                       __func__, lwtype_name(in->type));
                return;
        }
 
@@ -1565,7 +1565,8 @@ LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist)
        case COLLECTIONTYPE:
                return (LWGEOM*)lwcollection_simplify((LWCOLLECTION *)igeom, dist);
        default:
-               lwerror("lwgeom_simplify: unsupported geometry type: %s",lwtype_name(igeom->type));
+       lwerror("%s: unsupported geometry type: %s",
+               __func__, lwtype_name(igeom->type));
        }
        return NULL;
 }
@@ -1725,7 +1726,8 @@ lwgeom_affine(LWGEOM *geom, const AFFINE *affine)
                        }
                        else 
                        {
-                               lwerror("lwgeom_affine: unable to handle type '%s'", lwtype_name(type));
+                               lwerror("%s: unsupported geometry type: %s",
+                                       __func__, lwtype_name(type));
                        }
                }
        }
@@ -1756,8 +1758,8 @@ lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm)
                case COLLECTIONTYPE:
                        return lwcollection_as_lwgeom(lwcollection_construct_empty(type, srid, hasz, hasm));
                default:
-                       lwerror("lwgeom_construct_empty: unsupported geometry type: %s",
-                               lwtype_name(type));
+                       lwerror("%s: unsupported geometry type: %s",
+                               __func__, lwtype_name(type));
                        return NULL;
        }
 }
@@ -1786,8 +1788,8 @@ lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt)
                case COLLECTIONTYPE:
                        return lwcollection_startpoint((LWCOLLECTION*)lwgeom, pt);
                default:
-                       lwerror("int: unsupported geometry type: %s",
-                               lwtype_name(lwgeom->type));
+                       lwerror("%s: unsupported geometry type: %s",
+                               __func__, lwtype_name(lwgeom->type));
                        return LW_FAILURE;
        }
 }
@@ -1813,8 +1815,8 @@ lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
                case CIRCSTRINGTYPE:
                        return (LWGEOM *)lwcircstring_grid((LWCIRCSTRING *)lwgeom, grid);
                default:
-                       lwerror("lwgeom_grid: Unsupported geometry type: %s",
-                               lwtype_name(lwgeom->type));
+                       lwerror("%s: Unsupported geometry type: %s",
+                               __func__, lwtype_name(lwgeom->type));
                        return NULL;
        }
 }
@@ -1827,7 +1829,10 @@ lwgeom_npoints_in_rect(const LWGEOM *geom, const GBOX *gbox)
        
        if ( ! gbox_overlaps_2d(geombox, gbox) )
                return 0;
-       
+
+       if ( gbox_contains_2d(gbox, geombox) )
+               return lwgeom_count_vertices(geom);
+               
        switch ( geom->type )
        {
                case POINTTYPE:
@@ -1864,7 +1869,7 @@ lwgeom_npoints_in_rect(const LWGEOM *geom, const GBOX *gbox)
                }
                default:
                {
-                       lwerror("lwgeom_npoints_in_rect: Unsupported geometry type: %s",
+                       lwerror("%s: Unsupported geometry type: %s", __func__,
                                lwtype_name(geom->type));
                        return 0;
                }
@@ -1942,24 +1947,9 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, LWCOLLECTION *co
                                pt.y = clip->ymin;
                                if ( lwpoly_contains_point((LWPOLY*)geom, &pt) )
                                {
-                                       /* TODO: Probably just making the clipping box into a polygon is a more */
-                                       /* efficient way to do this? */
-                                       LWGEOM *clipped = lwgeom_clip_by_rect(geom, clip->xmin, clip->ymin, clip->xmax, clip->ymax);
-                                       /* Hm, clipping left nothing behind, skip it */
-                                       if ( lwgeom_is_empty(clipped) )
-                                       {
-                                               return 0;
-                                       }
-                                       /* Add the clipped part */
-                                       else
-                                       {
-                                               lwcollection_add_lwgeom(col, clipped);
-                                               return 5;
-                                       }
-                               }
-                               else
-                               {
-                                       return 0;
+                                       LWPOLY *clip_poly = lwpoly_construct_from_gbox(geom->srid, clip);
+                                       lwcollection_add_lwgeom(col, lwpoly_as_lwgeom(clip_poly));
+                                       return 5;
                                }
                        }
                        else
@@ -2021,6 +2011,11 @@ lwgeom_subdivide(const LWGEOM *geom, int maxvertices)
 {
        int n = 0;
        LWCOLLECTION *col;
+
+       /* Guard against terribleness */
+       if ( maxvertices < 10 )
+               lwerror("%s: must use a vertex count of at least 10", __func__);
+
        col = lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
        n = lwgeom_subdivide_recursive(geom, maxvertices, col, NULL);
        return col;
index de219908cc95164b8232ee4e4abd369162f303db..1b1339d8e5ba1dd275677ed7019a6f1c89f7e3c7 100644 (file)
@@ -76,6 +76,53 @@ lwpoly_construct_empty(int srid, char hasz, char hasm)
        return result;
 }
 
+LWPOLY*
+lwpoly_construct_from_gbox(int srid, const GBOX *gbox)
+{
+       POINTARRAY *pa;
+       POINT4D p;
+       LWPOLY *result = lwalloc(sizeof(LWPOLY));
+       result->type = POLYGONTYPE;
+       result->flags = gflags(0, 0, 0);
+       result->srid = srid;
+       result->nrings = 1;
+       result->maxrings = 1; /* Allocate room for ring, just in case. */
+       result->rings = lwalloc(result->maxrings * sizeof(POINTARRAY*));
+       result->bbox = gbox_clone(gbox);
+
+       /* Add a ring */
+       pa = ptarray_construct_empty(0, 0, 5);
+       result->rings[0] = pa;
+
+       /* 1st point */
+       p.x = gbox->xmin;
+       p.y = gbox->ymin;
+       ptarray_append_point(pa, &p, LW_TRUE);
+
+       /* 2nd point */
+       p.x = gbox->xmin;
+       p.y = gbox->ymax;
+       ptarray_append_point(pa, &p, LW_TRUE);
+
+       /* 3rd point */
+       p.x = gbox->xmax;
+       p.y = gbox->ymax;
+       ptarray_append_point(pa, &p, LW_TRUE);
+
+       /* 4th point */
+       p.x = gbox->xmax;
+       p.y = gbox->ymin;
+       ptarray_append_point(pa, &p, LW_TRUE);
+
+       /* 5th point */
+       p.x = gbox->xmin;
+       p.y = gbox->ymin;
+       ptarray_append_point(pa, &p, LW_TRUE);
+       
+       return result;
+}
+
+
 void lwpoly_free(LWPOLY  *poly)
 {
        int t;
index 2c137c0d23e211bac74552dcb7845048a9f4ba1c..a35dd1d3d8dd3f80744a3119cb23c5664063b850 100644 (file)
@@ -2099,52 +2099,21 @@ Datum ST_MakeEnvelope(PG_FUNCTION_ARGS)
 {
        LWPOLY *poly;
        GSERIALIZED *result;
-       POINTARRAY **pa;
-       POINT4D p;
-       double x1, y1, x2, y2;
+       GBOX gbox;
        int srid = SRID_UNKNOWN;
 
        POSTGIS_DEBUG(2, "ST_MakeEnvelope called");
 
-       x1 = PG_GETARG_FLOAT8(0);
-       y1 = PG_GETARG_FLOAT8(1);
-       x2 = PG_GETARG_FLOAT8(2);
-       y2 = PG_GETARG_FLOAT8(3);
+       gbox_init(&gbox);
+       gbox.xmin = PG_GETARG_FLOAT8(0);
+       gbox.ymin = PG_GETARG_FLOAT8(1);
+       gbox.xmax = PG_GETARG_FLOAT8(2);
+       gbox.ymax = PG_GETARG_FLOAT8(3);
        if ( PG_NARGS() > 4 ) {
                srid = PG_GETARG_INT32(4);
        }
 
-       pa = (POINTARRAY**)palloc(sizeof(POINTARRAY**));
-       pa[0] = ptarray_construct_empty(0, 0, 5);
-
-       /* 1st point */
-       p.x = x1;
-       p.y = y1;
-       ptarray_append_point(pa[0], &p, LW_TRUE);
-
-       /* 2nd point */
-       p.x = x1;
-       p.y = y2;
-       ptarray_append_point(pa[0], &p, LW_TRUE);
-
-       /* 3rd point */
-       p.x = x2;
-       p.y = y2;
-       ptarray_append_point(pa[0], &p, LW_TRUE);
-
-       /* 4th point */
-       p.x = x2;
-       p.y = y1;
-       ptarray_append_point(pa[0], &p, LW_TRUE);
-
-       /* 5th point */
-       p.x = x1;
-       p.y = y1;
-       ptarray_append_point(pa[0], &p, LW_TRUE);
-
-       poly = lwpoly_construct(srid, NULL, 1, pa);
-       lwgeom_add_bbox(lwpoly_as_lwgeom(poly));
-
+       poly = lwpoly_construct_from_gbox(srid, &gbox);
        result = geometry_serialize(lwpoly_as_lwgeom(poly));
        lwpoly_free(poly);
 
index b82207d7da6b5e6857f3c9366d82e28863af2950..b2757ba3c871397c1ccf914222e25e65509fee34 100644 (file)
@@ -23,3 +23,14 @@ CREATE TEMPORARY TABLE t AS SELECT
 SELECT ST_AsEWKT(ST_ClipByBox2d(g, ST_MakeEnvelope(-20,-20,-10,-10))) FROM t;
 -- See http://trac.osgeo.org/postgis/ticket/2954
 SELECT ST_AsEWKT(ST_ClipByBox2D('SRID=4326;POINT(0 0)','BOX3D(-1 -1,1 1)'::box3d::box2d));
+
+
+-- ST_Subdivide requires ST_ClibByBox2D
+SELECT Round(Sum(ST_Area(geom))), Count(*) 
+  FROM ST_Subdivide(ST_Segmentize('POLYGON((0 0, 0 100, 100 100, 100 0, 0 0))'::geometry,1),100) AS geom;
+
+SELECT Round(Sum(ST_Area(geom))), Count(*) 
+  FROM ST_Subdivide(ST_Segmentize('POLYGON((0 0, 0 100, 100 100, 100 0, 0 0))'::geometry,1),24) AS geom;
+
+SELECT Round(Sum(ST_Area(geom))), Count(*) 
+  FROM ST_Subdivide(ST_Segmentize('POLYGON((0 0, 0 100, 100 100, 100 0, 0 0))'::geometry,1),12) AS geom;
index e58bf780c5af4d7ebffa5975b78ff882e078b948..13571101f61bc2b870a20e7562ed96758cc0f871 100644 (file)
@@ -7,3 +7,6 @@ POLYGON((2.5 2,5 4,5 5,5 4,7.5 2,2.5 2))
 POLYGON((2 2,2 5,5 5,5 2,2 2))
 SRID=3857;POLYGON EMPTY
 SRID=4326;POINT(0 0)
+10000|13
+10000|64
+10000|148