[postgis-commits] svn - r3080 - in trunk: liblwgeom regress
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Wed Oct 8 03:14:46 PDT 2008
Author: mleslie
Date: 2008-10-08 03:14:46 -0700 (Wed, 08 Oct 2008)
New Revision: 3080
Modified:
trunk/liblwgeom/lwcurve.c
trunk/regress/sql-mm-circularstring.sql
trunk/regress/sql-mm-circularstring_expected.in
Log:
Rebuilt the box3d generation for circular strings to account for a special large-arc case. Fix for issue 58, includes regression test for the case.
Modified: trunk/liblwgeom/lwcurve.c
===================================================================
--- trunk/liblwgeom/lwcurve.c 2008-10-08 09:05:24 UTC (rev 3079)
+++ trunk/liblwgeom/lwcurve.c 2008-10-08 10:14:46 UTC (rev 3080)
@@ -258,10 +258,10 @@
{
double x1, x2, y1, y2, z1, z2;
double angle, radius, sweep;
- /*
- double top, left;
- */
+ // angles from center
double a1, a2, a3;
+ // angles from center once a1 is rotated to zero
+ double r2, r3;
double xe = 0.0, ye = 0.0;
POINT4D *center;
int i;
@@ -277,7 +277,7 @@
top = center->y + radius;
left = center->x - radius;
- LWDEBUGF(3, "lwcircle_compute_box3d: top=%.16f, left=%.16f", top, left);
+ LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);
*/
x1 = MAXFLOAT;
@@ -289,30 +289,55 @@
a2 = atan2(p2->y - center->y, p2->x - center->x);
a3 = atan2(p3->y - center->y, p3->x - center->x);
- /* Determine sweep angle */
- if(a1 > a2 && a2 > a3)
+ // Rotate a2 and a3 such that a1 = 0
+ r2 = a2 - a1;
+ r3 = a3 - a1;
+
+ /*
+ * There are six cases here I'm interested in
+ * Clockwise:
+ * 1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)
+ * 2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)
+ * 3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)
+ * Counter-clockwise:
+ * 4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)
+ * 5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)
+ * 6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)
+ * 3 and 6 are invalid cases where a3 is the midpoint.
+ * BBOX is fundamental, so these cannot error out and will instead
+ * calculate the sweep using a3 as the middle point.
+ */
+
+ // clockwise 1
+ if(r2 < 0 && (r3 > 0 || r3 < r2))
{
- sweep = a3 - a1;
+ sweep = (r3 > 0) ? (r3 - 2 * M_PI) : r3;
}
- /* Counter-clockwise */
- else if(a1 < a2 && a2 < a3)
+ // clockwise 2
+ else if(r2 > 0 && r3 > 0 && r3 < r2)
{
- sweep = a3 - a1;
+ sweep = (r3 > 0) ? (r3 - 2 * M_PI) : r3;
}
- /* Clockwise, wrap */
- else if((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3))
+ // counter-clockwise 4
+ else if(r2 > 0 && (r3 < 0 || r3 > r2))
{
- sweep = a3 - a1 + 2*M_PI;
+ sweep = (r3 < 0) ? (r3 + 2 * M_PI) : r3;
}
- /* Counter-clockwise, wrap */
- else if((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3))
+ // counter-clockwisk 5
+ else if(r2 < 0 && r3 < 0 && r3 > r2)
{
- sweep = a3 - a1 - 2*M_PI;
- }
- else
+ sweep = (r3 < 0) ? (r3 + 2 * M_PI) : r3;
+ }
+ // clockwise invalid 3
+ else if(r2 > 0 && (r3 > r2 || r3 < 0))
{
- sweep = 0.0;
+ sweep = (r2 > 0) ? (r2 - 2 * M_PI) : r2;
}
+ // clockwise invalid 6
+ else
+ {
+ sweep = (r2 < 0) ? (r2 + 2 * M_PI) : r2;
+ }
LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);
@@ -320,42 +345,69 @@
for(i=0; i < 6; i++)
{
switch(i) {
+ // right extent
case 0:
angle = 0.0;
xe = center->x + radius;
ye = center->y;
break;
+ // top extent
case 1:
angle = M_PI_2;
xe = center->x;
ye = center->y + radius;
break;
+ // left extent
case 2:
angle = M_PI;
xe = center->x - radius;
ye = center->y;
break;
+ // bottom extent
case 3:
angle = -1 * M_PI_2;
xe = center->x;
ye = center->y - radius;
break;
+ // first point
case 4:
angle = a1;
xe = p1->x;
ye = p1->y;
break;
+ // last point
case 5:
angle = a3;
xe = p3->x;
ye = p3->y;
break;
}
+ // determine if the extents are outside the arc
if(i < 4)
{
- if(sweep > 0.0 && (angle > a3 || angle < a1)) continue;
- if(sweep < 0.0 && (angle < a3 || angle > a1)) continue;
- }
+ if(sweep > 0.0)
+ {
+ if(a3 < a1)
+ {
+ if(angle > (a3 + 2 * M_PI) || angle < a1) continue;
+ }
+ else
+ {
+ if(angle > a3 || angle < a1) continue;
+ }
+ }
+ else
+ {
+ if(a3 > a1)
+ {
+ if(angle < (a3 - 2 * M_PI) || angle > a1) continue;
+ }
+ else
+ {
+ if(angle < a3 || angle > a1) continue;
+ }
+ }
+ }
LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);
Modified: trunk/regress/sql-mm-circularstring.sql
===================================================================
--- trunk/regress/sql-mm-circularstring.sql 2008-10-08 09:05:24 UTC (rev 3079)
+++ trunk/regress/sql-mm-circularstring.sql 2008-10-08 10:14:46 UTC (rev 3080)
@@ -384,3 +384,4 @@
SELECT DropGeometryColumn('public', 'circularstring', 'the_geom_3dm');
SELECT DropGeometryColumn('public', 'circularstring', 'the_geom_2d');
DROP TABLE public.circularstring;
+SELECT ST_asText(ST_box2d('CIRCULARSTRING(220268.439465645 150415.359530563,220227.333322076 150505.561285879,220227.353105332 150406.434743975)'::geometry));
Modified: trunk/regress/sql-mm-circularstring_expected.in
===================================================================
--- trunk/regress/sql-mm-circularstring_expected.in 2008-10-08 09:05:24 UTC (rev 3079)
+++ trunk/regress/sql-mm-circularstring_expected.in 2008-10-08 10:14:46 UTC (rev 3080)
@@ -203,3 +203,4 @@
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))
More information about the postgis-commits
mailing list