]> granicus.if.org Git - postgis/commitdiff
Rebuilt the box3d generation for circular strings to account for a special large...
authorMark Leslie <mark.leslie@lisasoft.com>
Wed, 8 Oct 2008 09:05:24 +0000 (09:05 +0000)
committerMark Leslie <mark.leslie@lisasoft.com>
Wed, 8 Oct 2008 09:05:24 +0000 (09:05 +0000)
git-svn-id: http://svn.osgeo.org/postgis/branches/1.3@3079 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwcurve.c
regress/sql-mm-circularstring.sql
regress/sql-mm-circularstring_expected.in

index 50110717465f027ad69812154baf278f210e5af0..211d33b73753989587e497ea2f5223808d9f0fc3 100644 (file)
@@ -34,7 +34,7 @@ lwcurve_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
 {\r
         LWCURVE *result;\r
         \r
-       /*\r
+    /*\r
          * The first arc requires three points.  Each additional\r
          * arc requires two more points.  Thus the minimum point count\r
          * is three, and the count must be odd.\r
@@ -272,10 +272,10 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
 {\r
         double x1, x2, y1, y2, z1, z2;\r
         double angle, radius, sweep;\r
-        /*\r
-        double top, left;\r
-        */\r
+       // angles from center\r
         double a1, a2, a3;\r
+        // angles from center once a1 is rotated to zero\r
+       double r2, r3;\r
         double xe = 0.0, ye = 0.0;\r
         POINT4D *center;\r
         int i;\r
@@ -285,18 +285,16 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
         lwnotice("lwcircle_compute_box3d called.");\r
 #endif\r
 \r
+        /*\r
+         * Determine where the center of the circle lives, and the radius.\r
+         */\r
         center = lwalloc(sizeof(POINT4D));\r
         radius = lwcircle_center(p1, p2, p3, &center);\r
         if(radius < 0.0) return NULL;\r
 \r
-        /*\r
-        top = center->y + radius;\r
-        left = center->x - radius;\r
-\r
 #ifdef PGIS_DEBUG_CALLS\r
-        lwnotice("lwcircle_compute_box3d: top=%.16f, left=%.16f", top, left);\r
+        lwnotice("lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);\r
 #endif\r
-        */\r
 \r
         x1 = MAXFLOAT;\r
         x2 = -1 * MAXFLOAT;\r
@@ -307,29 +305,54 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
         a2 = atan2(p2->y - center->y, p2->x - center->x);\r
         a3 = atan2(p3->y - center->y, p3->x - center->x);\r
 \r
-        /* Determine sweep angle */\r
-        if(a1 > a2 && a2 > a3) \r
+        // Rotate a2 and a3 such that a1 = 0\r
+        r2 = a2 - a1;\r
+        r3 = a3 - a1;\r
+\r
+        /*\r
+         * There are six cases here I'm interested in\r
+         * Clockwise:\r
+         *   1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)\r
+         *   2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)\r
+         *   3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)\r
+         * Counter-clockwise:\r
+         *   4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)\r
+         *   5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)\r
+         *   6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)\r
+         * 3 and 6 are invalid cases where a3 is the midpoint.\r
+         * BBOX is fundamental, so these cannot error out and will instead\r
+         * calculate the sweep using a3 as the middle point.\r
+         */\r
+\r
+        // clockwise 1\r
+        if(r2 < 0 && (r3 > 0 || r3 < r2))\r
         {\r
-                sweep = a3 - a1;\r
+            sweep = (r3 > 0) ? (r3 - 2 * M_PI) : r3;\r
         }\r
-        /* Counter-clockwise */\r
-        else if(a1 < a2 && a2 < a3)\r
+        // clockwise 2\r
+        else if(r2 > 0 && r3 > 0 && r3 < r2)\r
         {\r
-                sweep = a3 - a1;\r
+            sweep = (r3 > 0) ? (r3 - 2 * M_PI) : r3;\r
         }\r
-        /* Clockwise, wrap */\r
-        else if((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3))\r
+        // counter-clockwise 4\r
+        else if(r2 > 0 && (r3 < 0 || r3 > r2))\r
         {\r
-                sweep = a3 - a1 + 2*M_PI;\r
+            sweep = (r3 < 0) ? (r3 + 2 * M_PI) : r3;\r
         }\r
-        /* Counter-clockwise, wrap */\r
-        else if((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3))\r
+        // counter-clockwisk 5\r
+        else if(r2 < 0 && r3 < 0 && r3 > r2)\r
         {\r
-                sweep = a3 - a1 - 2*M_PI;\r
-        } \r
-        else \r
+            sweep = (r3 < 0) ? (r3 + 2 * M_PI) : r3;\r
+        }\r
+        // clockwise invalid 3\r
+        else if(r2 > 0 && (r3 > r2 || r3 < 0))\r
+        {\r
+            sweep = (r2 > 0) ? (r2 - 2 * M_PI) : r2;\r
+        }\r
+        // clockwise invalid 6\r
+        else\r
         {\r
-                sweep = 0.0;\r
+            sweep = (r2 < 0) ? (r2 + 2 * M_PI) : r2;\r
         }\r
 \r
 #ifdef PGIS_DEBUG\r
@@ -340,41 +363,68 @@ lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
         for(i=0; i < 6; i++)\r
         {\r
                 switch(i) {\r
+               // right extent\r
                 case 0:\r
                         angle = 0.0;\r
                         xe = center->x + radius;\r
                         ye = center->y;\r
                         break;\r
+               // top extent\r
                 case 1:\r
                         angle = M_PI_2;\r
                         xe = center->x;\r
                         ye = center->y + radius;\r
                         break;\r
+               // left extent\r
                 case 2:\r
                         angle = M_PI;\r
                         xe = center->x - radius;\r
                         ye = center->y;\r
                         break;\r
+               // bottom extent\r
                 case 3:\r
                         angle = -1 * M_PI_2;\r
                         xe = center->x;\r
                         ye = center->y - radius;\r
                         break;\r
+               // first point\r
                 case 4:\r
                         angle = a1;\r
                         xe = p1->x;\r
                         ye = p1->y;\r
                         break;\r
+               // last point\r
                 case 5:\r
                         angle = a3;\r
                         xe = p3->x;\r
                         ye = p3->y;\r
                         break;\r
                 }\r
+               // determine if the extents are outside the arc\r
                 if(i < 4) \r
                 {\r
-                        if(sweep > 0.0 && (angle > a3 || angle < a1)) continue;\r
-                        if(sweep < 0.0 && (angle < a3 || angle > a1)) continue;\r
+                    if(sweep > 0.0)\r
+                    {\r
+                       if(a3 < a1)\r
+                       {\r
+                           if(angle > (a3 + 2 * M_PI) || angle < a1) continue;\r
+                       }\r
+                       else\r
+                       {\r
+                           if(angle > a3 || angle < a1) continue;\r
+                       }\r
+                    }\r
+                    else\r
+                    {\r
+                       if(a3 > a1)\r
+                       {\r
+                           if(angle < (a3 - 2 * M_PI) || angle > a1) continue;\r
+                       }\r
+                       else\r
+                       {\r
+                          if(angle < a3 || angle > a1) continue;\r
+                       }\r
+                    }\r
                 }\r
 \r
 #ifdef PGIS_DEBUG\r
index 61e58583639cd773c863bdc480f59f255278af6f..56c4231da151fb7ec2635ba588e66f6e3da48e24 100644 (file)
@@ -384,3 +384,4 @@ SELECT DropGeometryColumn('public', 'circularstring', 'the_geom_3dz');
 SELECT DropGeometryColumn('public', 'circularstring', 'the_geom_3dm');\r
 SELECT DropGeometryColumn('public', 'circularstring', 'the_geom_2d');\r
 DROP TABLE public.circularstring;\r
+SELECT ST_asText(ST_box2d('CIRCULARSTRING(220268.439465645 150415.359530563,220227.333322076 150505.561285879,220227.353105332 150406.434743975)'::geometry));\r
index d3c05696339407dc3578263202dad2025602ee56..4fd82e091772f736594e4d52cbd38ba182b547e2 100644 (file)
@@ -203,3 +203,4 @@ public.circularstring.the_geom_4d effectively removed.
 public.circularstring.the_geom_3dz effectively removed.
 public.circularstring.the_geom_3dm effectively removed.
 public.circularstring.the_geom_2d effectively removed.
+POLYGON((220187.375 150406.421875,220187.375 150506.71875,220288.828125 150506.71875,220288.828125 150406.421875,220187.375 150406.421875))