]> granicus.if.org Git - postgis/commitdiff
Bounding box calculation for straight CircString fails (#668)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 17 Jun 2011 22:18:59 +0000 (22:18 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 17 Jun 2011 22:18:59 +0000 (22:18 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@7416 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/g_box.c
liblwgeom/liblwgeom.h
liblwgeom/lwcircstring.c
liblwgeom/lwsegmentize.c
regress/tickets.sql
regress/tickets_expected

index a8aea301c5fa226e1759aa4d177b75c357295e82..67620c716b0c98bef80cf18984c5cf1b98bc0870 100644 (file)
@@ -347,22 +347,31 @@ static int lwcircle_calculate_gbox_cartesian(POINT4D p1, POINT4D p2, POINT4D p3,
        /* angles from center once a1 is rotated to zero */
        double r2, r3;
        double xe = 0.0, ye = 0.0;
-       POINT4D *center;
+       POINT4D center;
        int i;
 
        LWDEBUG(2, "lwcircle_calculate_gbox called.");
 
        radius = lwcircle_center(&p1, &p2, &p3, &center);
-       if (radius < 0.0) return LW_FAILURE;
+       if (radius < 0.0) /* p1,p2,p3 are colinear */
+       {
+        gbox->xmin = FP_MIN(p1.x, p3.x);
+        gbox->ymin = FP_MIN(p1.y, p3.y);
+        gbox->zmin = FP_MIN(p1.z, p3.z);
+        gbox->xmax = FP_MAX(p1.x, p3.x);
+        gbox->ymax = FP_MAX(p1.y, p3.y);
+        gbox->zmax = FP_MAX(p1.z, p3.z);
+           return LW_SUCCESS;
+       }
 
        x1 = MAXFLOAT;
        x2 = -1 * MAXFLOAT;
        y1 = MAXFLOAT;
        y2 = -1 * MAXFLOAT;
 
-       a1 = atan2(p1.y - center->y, p1.x - center->x);
-       a2 = atan2(p2.y - center->y, p2.x - center->x);
-       a3 = atan2(p3.y - center->y, p3.x - center->x);
+       a1 = atan2(p1.y - center.y, p1.x - center.x);
+       a2 = atan2(p2.y - center.y, p2.x - center.x);
+       a3 = atan2(p3.y - center.y, p3.x - center.x);
 
        /* Rotate a2 and a3 such that a1 = 0 */
        r2 = a2 - a1;
@@ -424,26 +433,26 @@ static int lwcircle_calculate_gbox_cartesian(POINT4D p1, POINT4D p2, POINT4D p3,
                        /* right extent */
                case 0:
                        angle = 0.0;
-                       xe = center->x + radius;
-                       ye = center->y;
+                       xe = center.x + radius;
+                       ye = center.y;
                        break;
                        /* top extent */
                case 1:
                        angle = M_PI_2;
-                       xe = center->x;
-                       ye = center->y + radius;
+                       xe = center.x;
+                       ye = center.y + radius;
                        break;
                        /* left extent */
                case 2:
                        angle = M_PI;
-                       xe = center->x - radius;
-                       ye = center->y;
+                       xe = center.x - radius;
+                       ye = center.y;
                        break;
                        /* bottom extent */
                case 3:
                        angle = -1 * M_PI_2;
-                       xe = center->x;
-                       ye = center->y - radius;
+                       xe = center.x;
+                       ye = center.y - radius;
                        break;
                        /* first point */
                case 4:
index 212fb47403a4478b9b95042298c48c0574a466c3..ae01abba48b467d9d5f5a77f6c492e3aa93f0aeb 100644 (file)
@@ -2186,10 +2186,9 @@ void error_if_srid_mismatch(int srid1, int srid2);
  ******************************************************************************/
 
 int lwgeom_has_arc(const LWGEOM *geom);
-double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
+double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *result);
 LWGEOM *lwgeom_segmentize(LWGEOM *geom, uint32 perQuad);
 LWGEOM *lwgeom_desegmentize(LWGEOM *geom);
-double lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result);
 
 #endif /* !defined _LIBLWGEOM_H  */
 
index 14ebad91387ae2056386f18ffff692efcb4d1618..a255fce892c6598144a1feb164973d0ec8b52e3d 100644 (file)
@@ -290,21 +290,30 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
        /* angles from center once a1 is rotated to zero */
        double r2, r3;
        double xe = 0.0, ye = 0.0;
-       POINT4D *center;
+       POINT4D center;
        int i;
        BOX3D *box;
 
        LWDEBUG(2, "lwcircle_compute_box3d called.");
 
-       center = lwalloc(sizeof(POINT4D));
+       box = lwalloc(sizeof(BOX3D));
        radius = lwcircle_center(p1, p2, p3, &center);
-       if (radius < 0.0) return NULL;
+       if (radius < 0.0) 
+       {
+        box->xmin = FP_MIN(p1->x, p3->x);
+        box->ymin = FP_MIN(p1->y, p3->y);
+        box->zmin = FP_MIN(p1->z, p3->z);
+        box->xmax = FP_MAX(p1->x, p3->x);
+        box->ymax = FP_MAX(p1->y, p3->y);
+        box->zmax = FP_MAX(p1->z, p3->z);
+        return box;
+       }
 
        /*
-       top = center->y + radius;
-       left = center->x - radius;
+       top = center.y + radius;
+       left = center.x - radius;
 
-       LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);
+       LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center.x, center.y);
        */
 
        x1 = MAXFLOAT;
@@ -312,9 +321,9 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
        y1 = MAXFLOAT;
        y2 = -1 * MAXFLOAT;
 
-       a1 = atan2(p1->y - center->y, p1->x - center->x);
-       a2 = atan2(p2->y - center->y, p2->x - center->x);
-       a3 = atan2(p3->y - center->y, p3->x - center->x);
+       a1 = atan2(p1->y - center.y, p1->x - center.x);
+       a2 = atan2(p2->y - center.y, p2->x - center.x);
+       a3 = atan2(p3->y - center.y, p3->x - center.x);
 
        /* Rotate a2 and a3 such that a1 = 0 */
        r2 = a2 - a1;
@@ -376,26 +385,26 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
                        /* right extent */
                case 0:
                        angle = 0.0;
-                       xe = center->x + radius;
-                       ye = center->y;
+                       xe = center.x + radius;
+                       ye = center.y;
                        break;
                        /* top extent */
                case 1:
                        angle = M_PI_2;
-                       xe = center->x;
-                       ye = center->y + radius;
+                       xe = center.x;
+                       ye = center.y + radius;
                        break;
                        /* left extent */
                case 2:
                        angle = M_PI;
-                       xe = center->x - radius;
-                       ye = center->y;
+                       xe = center.x - radius;
+                       ye = center.y;
                        break;
                        /* bottom extent */
                case 3:
                        angle = -1 * M_PI_2;
-                       xe = center->x;
-                       ye = center->y - radius;
+                       xe = center.x;
+                       ye = center.y - radius;
                        break;
                        /* first point */
                case 4:
@@ -448,17 +457,16 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
        LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);
 
        /*
-       x1 = center->x + x1 * radius;
-       x2 = center->x + x2 * radius;
-       y1 = center->y + y1 * radius;
-       y2 = center->y + y2 * radius;
+       x1 = center.x + x1 * radius;
+       x2 = center.x + x2 * radius;
+       y1 = center.y + y1 * radius;
+       y2 = center.y + y2 * radius;
        */
        z1 = (FP_LT(p1->z, p2->z)) ? p1->z : p2->z;
        z1 = (FP_LT(z1, p3->z)) ? z1 : p3->z;
        z2 = (FP_GT(p1->z, p2->z)) ? p1->z : p2->z;
        z2 = (FP_GT(z2, p3->z)) ? z2 : p3->z;
 
-       box = lwalloc(sizeof(BOX3D));
        box->xmin = x1;
        box->xmax = x2;
        box->ymin = y1;
@@ -466,8 +474,6 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
        box->zmin = z1;
        box->zmax = z2;
 
-       lwfree(center);
-
        return box;
 }
 
index 951e4b48755427b89f47d0cfda51f55ada382400..6e2a419906eb551ce5423ee91e36756f3daba7f9 100644 (file)
@@ -85,12 +85,14 @@ lwgeom_has_arc(const LWGEOM *geom)
  * point is coincident with either end point, they are taken as colinear.
  */
 double
-lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result)
+lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *result)
 {
-       POINT4D *c;
+       POINT4D c;
        double cx, cy, cr;
        double temp, bc, cd, det;
 
+    c.x = c.y = c.z = c.m = 0.0;
+
        LWDEBUGF(2, "lwcircle_center called (%.16f, %.16f), (%.16f, %.16f), (%.16f, %.16f).", p1->x, p1->y, p2->x, p2->y, p3->x, p3->y);
 
        /* Closed circle */
@@ -99,9 +101,8 @@ lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result)
        {
                cx = p1->x + (p2->x - p1->x) / 2.0;
                cy = p1->y + (p2->y - p1->y) / 2.0;
-               c = lwalloc(sizeof(POINT2D));
-               c->x = cx;
-               c->y = cy;
+               c.x = cx;
+               c.y = cy;
                *result = c;
                cr = sqrt((cx-p1->x)*(cx-p1->x)+(cy-p1->y)*(cy-p1->y));
                return cr;
@@ -114,17 +115,14 @@ lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result)
 
        /* Check colinearity */
        if (fabs(det) < EPSILON_SQLMM)
-       {
-               *result = NULL;
                return -1.0;
-       }
+
 
        det = 1.0 / det;
        cx = (bc*(p2->y - p3->y)-cd*(p1->y - p2->y))*det;
        cy = ((p1->x - p2->x)*cd-(p2->x - p3->x)*bc)*det;
-       c = lwalloc(sizeof(POINT4D));
-       c->x = cx;
-       c->y = cy;
+       c.x = cx;
+       c.y = cy;
        *result = c;
        cr = sqrt((cx-p1->x)*(cx-p1->x)+(cy-p1->y)*(cy-p1->y));
        return cr;
@@ -156,7 +154,7 @@ lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad)
        uint32 ptcount;
        uchar *pt;
 
-       POINT4D *center;
+       POINT4D center;
        double radius = 0.0,
                        sweep = 0.0,
                                angle = 0.0,
@@ -174,11 +172,11 @@ lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad)
                return NULL;
        }
 
-       LWDEBUGF(3, "lwcircle_segmentize, (%.16f, %.16f) radius=%.16f", center->x, center->y, radius);
+       LWDEBUGF(3, "lwcircle_segmentize, (%.16f, %.16f) radius=%.16f", center.x, center.y, radius);
 
-       a1 = atan2(p1->y - center->y, p1->x - center->x);
-       a2 = atan2(p2->y - center->y, p2->x - center->x);
-       a3 = atan2(p3->y - center->y, p3->x - center->x);
+       a1 = atan2(p1->y - center.y, p1->x - center.x);
+       a2 = atan2(p2->y - center.y, p2->x - center.x);
+       a3 = atan2(p3->y - center.y, p3->x - center.x);
 
        LWDEBUGF(3, "a1 = %.16f, a2 = %.16f, a3 = %.16f", a1, a2, a3);
 
@@ -228,8 +226,8 @@ lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad)
                angle += increment;
                if (increment > 0.0 && angle > M_PI) angle -= 2*M_PI;
                if (increment < 0.0 && angle < -1*M_PI) angle -= 2*M_PI;
-               pbuf.x = center->x + radius*cos(angle);
-               pbuf.y = center->y + radius*sin(angle);
+               pbuf.x = center.x + radius*cos(angle);
+               pbuf.y = center.y + radius*sin(angle);
                if ((sweep > 0 && angle < a2) || (sweep < 0 && angle > a2))
                {
                        if ((sweep > 0 && a1 < a2) || (sweep < 0 && a1 > a2))
@@ -278,8 +276,6 @@ lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad)
        pt = getPoint_internal(result, ptcount - 1);
        memcpy(pt, (uchar *)p3, ptsize);
 
-       lwfree(center);
-
        return result;
 }
 
index cade7fcb8afb9adf7c00508731e3682877ad19fc..19323d2533c97cab9016f158e81682e3600e6579 100644 (file)
@@ -384,5 +384,8 @@ select '#938', 'POLYGON EMPTY'::geometry::box2d;
 
 DROP TABLE foo;
 
+-- #668 --
+select '#668',box2d('CIRCULARSTRING(10 2,12 2,14 2)'::geometry) as b;
+
 -- Clean up
 DELETE FROM spatial_ref_sys;
index 607563d8c5fde24afac36c78e0aa16529c2a8589..39a3ad517be173c519dde69c9539b92bb166d48f 100644 (file)
@@ -111,3 +111,4 @@ ERROR:  First argument must be a LINESTRING
 #884|1|f
 #884|2|t
 #938|
+#668|BOX(10 2,14 2)