]> granicus.if.org Git - postgis/commitdiff
Commit Charlie Savage's patches (with additional comments) to the bounding box/envelo...
authorMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Mon, 29 Oct 2007 13:44:29 +0000 (13:44 +0000)
committerMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Mon, 29 Oct 2007 13:44:29 +0000 (13:44 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@2713 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwgeom_box2dfloat4.c
lwgeom/lwgeom_box3d.c
lwgeom/lwgeom_functions_basic.c

index f6d6f062e3d9d035f2c7733a4e89a1d7e60c9938..c8ba9d307c5a8a434fcecd27ce8f37787c42f111 100644 (file)
@@ -456,32 +456,69 @@ PG_FUNCTION_INFO_V1(BOX2DFLOAT4_to_LWGEOM);
 Datum BOX2DFLOAT4_to_LWGEOM(PG_FUNCTION_ARGS)
 {
        BOX2DFLOAT4 *box = (BOX2DFLOAT4 *)PG_GETARG_POINTER(0);
-       POINT2D *pts = palloc(sizeof(POINT2D)*5);
-       POINTARRAY *pa[1];
-       LWPOLY *poly;
+       POINTARRAY *pa;
        int wantbbox = 0;
        PG_LWGEOM *result;
        uchar *ser;
 
-       /* Assign coordinates to POINT2D array */
-       pts[0].x = box->xmin; pts[0].y = box->ymin;
-       pts[1].x = box->xmin; pts[1].y = box->ymax;
-       pts[2].x = box->xmax; pts[2].y = box->ymax;
-       pts[3].x = box->xmax; pts[3].y = box->ymin;
-       pts[4].x = box->xmin; pts[4].y = box->ymin;
-
-       /* Construct point array */
-       pa[0] = palloc(sizeof(POINTARRAY));
-       pa[0]->serialized_pointlist = (uchar *)pts;
-       TYPE_SETZM(pa[0]->dims, 0, 0);
-       pa[0]->npoints = 5;
-
-       /* Construct polygon */
-       poly = lwpoly_construct(-1, NULL, 1, pa);
-
-       /* Serialize polygon */
-       ser = lwpoly_serialize(poly);
 
+       /* 
+        * Alter BOX2D cast so that a valid geometry is always
+        * returned depending upon the size of the BOX2D. The
+        * code makes the following assumptions:
+        *     - If the BOX2D is a single point then return a
+        *     POINT geometry
+        *     - If the BOX2D represents either a horizontal or
+        *     vertical line, return a LINESTRING geometry
+        *     - Otherwise return a POLYGON
+        */
+
+       if (box->xmin == box->xmax &&
+           box->ymin == box->ymax)
+        {
+         /* Construct and serialize point */
+          LWPOINT *point = make_lwpoint2d(-1, box->xmin, box->ymin);
+         ser = lwpoint_serialize(point);
+        }
+       else if (box->xmin == box->xmax ||
+                box->ymin == box->ymax)
+        {
+         LWLINE *line;
+         POINT2D *pts = palloc(sizeof(POINT2D)*2);
+         
+         /* Assign coordinates to POINT2D array */
+         pts[0].x = box->xmin; pts[0].y = box->ymin;
+         pts[1].x = box->xmax; pts[1].y = box->ymax;
+         
+         /* Construct point array */
+          pa = pointArray_construct((uchar *)pts, 0, 0, 2);      
+
+         /* Construct and serialize linestring */
+         line = lwline_construct(-1, NULL, pa);
+         ser = lwline_serialize(line);
+        }
+        else
+        {
+         LWPOLY *poly;
+         POINT2D *pts = palloc(sizeof(POINT2D)*5);
+
+         /* Assign coordinates to POINT2D array */
+         pts[0].x = box->xmin; pts[0].y = box->ymin;
+         pts[1].x = box->xmin; pts[1].y = box->ymax;
+         pts[2].x = box->xmax; pts[2].y = box->ymax;
+         pts[3].x = box->xmax; pts[3].y = box->ymin;
+         pts[4].x = box->xmin; pts[4].y = box->ymin;
+
+         /* Construct point array */
+          pa = pointArray_construct((uchar *)pts, 0, 0, 5);      
+
+         /* Construct polygon */
+         poly = lwpoly_construct(-1, NULL, 1, &pa);
+
+         /* Serialize polygon */
+         ser = lwpoly_serialize(poly);
+        }
+        
        /* Construct PG_LWGEOM  */
        result = PG_LWGEOM_construct(ser, -1, wantbbox);
        
index 0e21d926f6853e1791a78dd0d671007c3b3056f7..42cf9075cae5eff8c092216bc8b2e3dc5905b3f5 100644 (file)
@@ -162,32 +162,69 @@ PG_FUNCTION_INFO_V1(BOX3D_to_LWGEOM);
 Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
 {
        BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
-       POINT2D *pts = palloc(sizeof(POINT2D)*5);
-       POINTARRAY *pa[1];
-       LWPOLY *poly;
+       POINTARRAY *pa;
        int wantbbox = 0;
        PG_LWGEOM *result;
        uchar *ser;
 
-       /* Assign coordinates to POINT2D array */
-       pts[0].x = box->xmin; pts[0].y = box->ymin;
-       pts[1].x = box->xmin; pts[1].y = box->ymax;
-       pts[2].x = box->xmax; pts[2].y = box->ymax;
-       pts[3].x = box->xmax; pts[3].y = box->ymin;
-       pts[4].x = box->xmin; pts[4].y = box->ymin;
-
-       /* Construct point array */
-       pa[0] = palloc(sizeof(POINTARRAY));
-       pa[0]->serialized_pointlist = (uchar *)pts;
-       TYPE_SETZM(pa[0]->dims, 0, 0);
-       pa[0]->npoints = 5;
-
-       /* Construct polygon */
-       poly = lwpoly_construct(-1, NULL, 1, pa);
-
-       /* Serialize polygon */
-       ser = lwpoly_serialize(poly);
 
+       /* 
+        * Alter BOX3D cast so that a valid geometry is always
+        * returned depending upon the size of the BOX3D. The
+        * code makes the following assumptions:
+        *     - If the BOX3D is a single point then return a
+        *     POINT geometry
+        *     - If the BOX3D represents either a horizontal or
+        *     vertical line, return a LINESTRING geometry
+        *     - Otherwise return a POLYGON
+        */
+
+       if (box->xmin == box->xmax &&
+           box->ymin == box->ymax)
+        {
+         /* Construct and serialize point */
+          LWPOINT *point = make_lwpoint2d(-1, box->xmin, box->ymin);
+         ser = lwpoint_serialize(point);
+        }
+       else if (box->xmin == box->xmax ||
+                box->ymin == box->ymax)
+        {
+         LWLINE *line;
+         POINT2D *pts = palloc(sizeof(POINT2D)*2);
+         
+         /* Assign coordinates to POINT2D array */
+         pts[0].x = box->xmin; pts[0].y = box->ymin;
+         pts[1].x = box->xmax; pts[1].y = box->ymax;
+         
+         /* Construct point array */
+          pa = pointArray_construct((uchar *)pts, 0, 0, 2);      
+
+         /* Construct and serialize linestring */
+         line = lwline_construct(-1, NULL, pa);
+         ser = lwline_serialize(line);
+        }
+        else
+        {
+         LWPOLY *poly;
+         POINT2D *pts = palloc(sizeof(POINT2D)*5);
+
+         /* Assign coordinates to POINT2D array */
+         pts[0].x = box->xmin; pts[0].y = box->ymin;
+         pts[1].x = box->xmin; pts[1].y = box->ymax;
+         pts[2].x = box->xmax; pts[2].y = box->ymax;
+         pts[3].x = box->xmax; pts[3].y = box->ymin;
+         pts[4].x = box->xmin; pts[4].y = box->ymin;
+
+         /* Construct point array */
+          pa = pointArray_construct((uchar *)pts, 0, 0, 5);      
+
+         /* Construct polygon */
+         poly = lwpoly_construct(-1, NULL, 1, &pa);
+
+         /* Serialize polygon */
+         ser = lwpoly_serialize(poly);
+        }
+        
        /* Construct PG_LWGEOM  */
        result = PG_LWGEOM_construct(ser, -1, wantbbox);
        
index 76b3aeed318594774e461cbc10b6ec3265f12e3a..e8c9ef728973870cefb85548e29a8237b6ea6b95 100644 (file)
@@ -2493,55 +2493,85 @@ PG_FUNCTION_INFO_V1(LWGEOM_envelope);
 Datum LWGEOM_envelope(PG_FUNCTION_ARGS)
 {
        PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       BOX2DFLOAT4 box;
-       POINT2D *pts = lwalloc(sizeof(POINT2D)*5);
-       POINTARRAY *pa[1];
-       LWPOLY *poly;
+       BOX3D box;
        int SRID;
+       POINTARRAY *pa;
        PG_LWGEOM *result;
-       uchar *ser;
+       uchar *ser = NULL;
 
-       if (lwgeom_getType(geom->type) == POINTTYPE ||
-            (lwgeom_getType(geom->type) == MULTIPOINTTYPE && lwgeom_getnumgeometries(SERIALIZED_FORM(geom)) == 1))
-       {
-               int srid = lwgeom_getsrid(SERIALIZED_FORM(geom));
-               LWPOINT* point = lwgeom_getpoint(SERIALIZED_FORM(geom), 0);
-               LWPOINT* envelope = lwpoint_construct(srid, NULL, point->point);
-               ser = lwpoint_serialize(envelope);
-               result = PG_LWGEOM_construct(ser, srid, 0);
-       PG_RETURN_POINTER(result);
-       }
 
        /* get bounding box  */
-       if ( ! getbox2d_p(SERIALIZED_FORM(geom), &box) )
+       if ( ! compute_serialized_box3d_p(SERIALIZED_FORM(geom), &box) )
        {
                /* must be the EMPTY geometry */
                PG_RETURN_POINTER(geom);
        }
-
+       
        /* get geometry SRID */
        SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
 
-       PG_FREE_IF_COPY(geom, 0);
+       
+       /* 
+        * Alter envelope type so that a valid geometry is always
+        * returned depending upon the size of the geometry. The
+        * code makes the following assumptions:
+        *     - If the bounding box is a single point then return a
+        *     POINT geometry
+        *     - If the bounding box represents either a horizontal or
+        *     vertical line, return a LINESTRING geometry
+        *     - Otherwise return a POLYGON
+        */
 
-       /* Assign coordinates to POINT2D array */
-       pts[0].x = box.xmin; pts[0].y = box.ymin;
-       pts[1].x = box.xmin; pts[1].y = box.ymax;
-       pts[2].x = box.xmax; pts[2].y = box.ymax;
-       pts[3].x = box.xmax; pts[3].y = box.ymin;
-       pts[4].x = box.xmin; pts[4].y = box.ymin;
 
-       /* Construct point array */
-       pa[0] = lwalloc(sizeof(POINTARRAY));
-       pa[0]->serialized_pointlist = (uchar *)pts;
-       TYPE_SETZM(pa[0]->dims, 0, 0);
-       pa[0]->npoints = 5;
+       if (box.xmin == box.xmax &&
+           box.ymin == box.ymax)
+        {
+                /* Construct and serialize point */
+                LWPOINT *point = make_lwpoint2d(SRID, box.xmin, box.ymin);
+                ser = lwpoint_serialize(point);
+        }
+       else if (box.xmin == box.xmax ||
+                box.ymin == box.ymax)
+        {
+                LWLINE *line;
+                POINT2D *pts = palloc(sizeof(POINT2D)*2);
 
-       /* Construct polygon  */
-       poly = lwpoly_construct(SRID, box2d_clone(&box), 1, pa);
+                /* Assign coordinates to POINT2D array */
+                pts[0].x = box.xmin; pts[0].y = box.ymin;
+                pts[1].x = box.xmax; pts[1].y = box.ymax;
+
+                /* Construct point array */
+                pa = pointArray_construct((uchar *)pts, 0, 0, 2);        
 
-       /* Serialize polygon */
-       ser = lwpoly_serialize(poly);
+                /* Construct and serialize linestring */
+                line = lwline_construct(SRID, NULL, pa);
+                ser = lwline_serialize(line);
+        }
+        else
+        {
+                LWPOLY *poly;
+               POINT2D *pts = lwalloc(sizeof(POINT2D)*5);
+                BOX2DFLOAT4 box2d;
+                getbox2d_p(SERIALIZED_FORM(geom), &box2d);
+               
+                /* Assign coordinates to POINT2D array */
+                pts[0].x = box2d.xmin; pts[0].y = box2d.ymin;
+                pts[1].x = box2d.xmin; pts[1].y = box2d.ymax;
+                pts[2].x = box2d.xmax; pts[2].y = box2d.ymax;
+                pts[3].x = box2d.xmax; pts[3].y = box2d.ymin;
+                pts[4].x = box2d.xmin; pts[4].y = box2d.ymin;
+
+                /* Construct point array */
+                pa = pointArray_construct((uchar *)pts, 0, 0, 5);
+
+                /* Construct polygon  */
+                poly = lwpoly_construct(SRID, box2d_clone(&box2d), 1, &pa);
+
+                /* Serialize polygon */
+                ser = lwpoly_serialize(poly);
+        }
+                       
+       PG_FREE_IF_COPY(geom, 0);
 
        /* Construct PG_LWGEOM  */
        result = PG_LWGEOM_construct(ser, SRID, 1);