Fix computation of number of quadrants per arc (#2420)
authorSandro Santilli <strk@keybit.net>
Tue, 13 Aug 2013 23:48:04 +0000 (23:48 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 13 Aug 2013 23:48:04 +0000 (23:48 +0000)
Note: I had to change some tests that expected 3-quadrant curves
      to be accepted as curvey input to rely on round-trip instead

git-svn-id: http://svn.osgeo.org/postgis/trunk@11794 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_ptarray.c
liblwgeom/lwsegmentize.c
regress/tickets.sql
regress/tickets_expected

index 933aa062ead5aec5612cb636f2bcec170b4d07b6..6078f54d7c8d92c1d1188e1a44f768812c21ccd2 100644 (file)
@@ -361,34 +361,50 @@ static void test_ptarray_desegmentize()
        lwfree(str);    
        */
        
-       in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1)");
+       in = lwgeom_from_text("CIRCULARSTRING(-1 0,0 1,0 -1)");
+       out = lwgeom_segmentize(in,8);
+       lwgeom_free(in);
+  in = out;
        out = lwgeom_desegmentize(in);
        str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
-       CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0 1,0 -1)");
+       //printf("%s\n", str);
+       CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1)");
        lwgeom_free(in);
        lwgeom_free(out);
        lwfree(str);    
 
-       in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 -1)");
+       in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,-1 -1))");
+       out = lwgeom_segmentize(in,8);
+       lwgeom_free(in);
+  in = out;
        out = lwgeom_desegmentize(in);
        str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
-       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,-1 -1))");
+       //printf("%s\n", str);
+       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,-1 -1))");
        lwgeom_free(in);
        lwgeom_free(out);
        lwfree(str);    
 
-       in = lwgeom_from_text("LINESTRING(-3 -3,-1 0, 0 1, 1 0, 0 -1, 0 -1.5, 0 -2, -1 -3, 0 -4, 1 -3,5 5)");
+       in = lwgeom_from_text("COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-1 -3,1 -3),(1 -3,5 5))");
+       out = lwgeom_segmentize(in,8);
+       lwgeom_free(in);
+  in = out;
        out = lwgeom_desegmentize(in);
        str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
-       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-1 -3,1 -3),(1 -3,5 5))");
+       //printf("%s\n", str);
+       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-0.70710678 -3.7071068,1 -3),(1 -3,5 5))");
        lwgeom_free(in);
        lwgeom_free(out);
        lwfree(str);    
 
-       in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 -2, 0 -3, 1 -2)");
+       in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),CIRCULARSTRING(0 -1,-1 -2,1 -2))");
+       out = lwgeom_segmentize(in,8);
+       lwgeom_free(in);
+  in = out;
        out = lwgeom_desegmentize(in);
        str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
-       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),CIRCULARSTRING(0 -1,-1 -2,1 -2))");
+       //printf("%s\n", str);
+       CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),CIRCULARSTRING(0 -1,-0.70710678 -2.7071068,1 -2))");
        lwgeom_free(in);
        lwgeom_free(out);
        lwfree(str);    
index 2fd5d063ea80c0f7177981763d25121748ad7fc0..47966e67a745ca6b81d81bfe36409f3f43fba019 100644 (file)
@@ -587,7 +587,7 @@ pta_desegmentize(POINTARRAY *points, int type, int srid)
 {
        int i = 0, j, k;
        POINT4D a1, a2, a3, b;
-       POINT4D first;
+       POINT4D first, center;
        char *edges_in_arcs;
        int found_arc = LW_FALSE;
        int current_arc = 1;
@@ -623,7 +623,8 @@ pta_desegmentize(POINTARRAY *points, int type, int srid)
        while( i < num_edges-2 )
        {
                unsigned int arc_edges;
-               unsigned int num_quadrants;
+               double num_quadrants;
+               double angle;
 
                found_arc = LW_FALSE;
                /* Make candidate arc */
@@ -665,15 +666,24 @@ pta_desegmentize(POINTARRAY *points, int type, int srid)
                         * See http://trac.osgeo.org/postgis/ticket/2420
                         */
                        arc_edges = j - 1 - i;
-                       num_quadrants = 1; /* silly guess, TODO: compute */
                        LWDEBUGF(4, "arc defined by %d edges found", arc_edges);
                        if ( first.x == b.x && first.y == b.y ) {
                                LWDEBUG(4, "arc is a circle");
                                num_quadrants = 4;
                        }
+                       else {
+                               lw_arc_center((POINT2D*)&first, (POINT2D*)&b, (POINT2D*)&a1, (POINT2D*)&center);
+                               angle = lw_arc_angle((POINT2D*)&first, (POINT2D*)&center, (POINT2D*)&b);
+        int p2_side = lw_segment_side((POINT2D*)&first, (POINT2D*)&a1, (POINT2D*)&b);
+        if ( p2_side != -1 ) angle = -angle; 
+
+                               if ( angle < 0 ) angle = 2 * M_PI + angle;
+                               num_quadrants = ( 4 * angle ) / ( 2 * M_PI );
+                               LWDEBUGF(4, "arc angle is %g, quandrants:%g", angle, num_quadrants);
+                       }
                        /* a1 is first point, b is last point */
                        if ( arc_edges < min_quad_edges * num_quadrants ) {
-                               LWDEBUGF(4, "Not enough edges for a %d quadrants arc", num_quadrants);
+                               LWDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
                                for ( k = j-1; k >= i; k-- )
                                        edges_in_arcs[k] = 0;
                        }
index 333b767bc176a8c32e80cb7ee102754e6b0d58ad..48bedd77d3980d18aedf972c709ea5b1756d16a9 100644 (file)
@@ -831,7 +831,8 @@ SELECT '#2415.2', ST_AsText(ST_Multi(
 
 SELECT '#2412', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,20 0)'));
 
-SELECT '#2420', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10,0 0)'));
+SELECT '#2420.1', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10,0 0)'));
+SELECT '#2420.2', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10)'));
 
 SELECT '#2423', ST_AsText(ST_SnapToGrid(ST_CurveToLine(ST_LineToCurve(
   ST_Intersection(ST_Buffer(ST_Point(0,0),10),ST_MakeEnvelope(-10,0,10,10))
index 6dd393717c27ebb58a93d42edb3522e748ba5798..1e34dbdcea1b1cd0621fd9a36f50699f52917b66 100644 (file)
@@ -247,7 +247,8 @@ ERROR:  invalid GML representation
 #2415.1|MULTICURVE(COMPOUNDCURVE((0 0,10 0),CIRCULARSTRING(10 0,15 1,20 10)))
 #2415.2|MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(10 0,15 1,20 0,18 5,20 10,10 10,10 0)))
 #2412|LINESTRING(0 0,10 0,20 0)
-#2420|LINESTRING(0 0,10 0,10 10,0 10,0 0)
+#2420.1|LINESTRING(0 0,10 0,10 10,0 10,0 0)
+#2420.2|LINESTRING(0 0,10 0,10 10,0 10)
 #2423|POLYGON((-10 0,-9.2388 3.82683,-7.07107 7.07107,-3.82683 9.2388,0 10,3.82683 9.2388,7.07107 7.07107,9.2388 3.82683,10 0,-10 0))
 #2424|MULTILINESTRING((0 0,10 0,24 3,30 10))
 #2427|POINT(-1 0)